<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=46.128.38.250</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=46.128.38.250"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/46.128.38.250"/>
	<updated>2026-04-11T01:28:04Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Digitalfilter_mit_ATmega&amp;diff=80970</id>
		<title>Digitalfilter mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Digitalfilter_mit_ATmega&amp;diff=80970"/>
		<updated>2014-01-19T16:39:37Z</updated>

		<summary type="html">&lt;p&gt;46.128.38.250: Erklärung IIR korrigiert, Nachteil von Filtern höherer Ordnung korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auch mit 8-Bit-Mikrocontrollern der ATmega-Reihe ist es möglich, einfache digitale Signalverarbeitungen auszuführen. Mittels kostenloser Mathematiksoftware ist die Berechnung eigener Filter möglich.&lt;br /&gt;
&lt;br /&gt;
Viele von uns haben schon analoge Filterschaltungen aufgebaut, als passive LC-Filter oder aktive Filter mit Operationsverstärkern. Dank kostenloser Berechnungssoftware, wie z.&amp;amp;nbsp;B. [http://www.aade.com AADE], ist die Auswahl der Schaltung und Berechnung der Bauteilwerte kein Problem mehr. Die gleichen Filter in digitaler Technik zu erstellen gilt dagegen immer noch als kompliziert, obwohl sie in professionellen Schaltungen die Analogtechnik weitgehend verdrängt haben. Ihr großer Vorteil ist der fehlende Abgleich. Dank Quarzoszillator wird ein einmal berechneter Frequenzgang ohne Präzisionsbauteile reproduzierbar eingehalten.&lt;br /&gt;
 &lt;br /&gt;
Die Software ist im Grunde sehr einfach aufgebaut, besteht nur aus Schiebeoperationen, Additionen und einigen Multiplikationen. Die ATmega-Controller enthalten alle dazu nötigen Funktionen, einen A/D-Wandler, einen 8-Bit Multiplizierer und mehrere D/A-Wandler durch Pulsbreitenmodulation. Am Ausgang muß nur noch ein [http://www.mikrocontroller.net/articles/AVR_PWM#Tiefpassfilter-Berechnung einfacher Tiefpaß] die PWM-Frequenz wegfiltern. Die Programmbeispiele wurden auf Grundlage der [http://www.atmel.com/dyn/resources/prod_documents/doc2527.pdf Applikationsschrift AVR223] mit [http://atmel.com/avrstudio AVRStudio] entwickelt.&lt;br /&gt;
&lt;br /&gt;
Am Ende der Programme befindet sich eine Koeffiziententabelle, deren Werte die Filtereigenschaften bestimmen. Um eigene Filter entwickeln zu können sollen dazu die Grundbegriffe sehr kurz erläutert und dann einfache „Kochrezepte“ vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
===Ein IIR-Filter 6. Ordnung===&lt;br /&gt;
Als erstes wird ein Filter berechnet, das nur durch Änderung der Koeffizienten als Tiefpaß, Hochpaß, Bandpaß oder Bandsperre wirkt. Im Beispielprogramm soll es ein 1750 Hz Sperrfilter werden, das laute Ruftöne beim Zuhören auf Amateur-Relaisfunkstellen unterdrücken kann.&lt;br /&gt;
Dieser Filtertyp heißt „IIR“, &#039;&#039;infinite impulse response&#039;&#039;, weil er nach Anregung mit einem Impuls theoretisch eine unendliche Impulsantwort liefert. Der verwendete Aufbau aus drei hintereinandergeschalteten Teilfiltern zweiter Ordnung ist als gutmütig bekannt. Diese &#039;&#039;kaskadierten&#039;&#039; Teilfilter nennt man „SOS“ &#039;&#039;second order sections&#039;&#039; oder auch &#039;&#039;biquad sections&#039;&#039;. Der Aufbau mit einem einzigen Filter 6. Ordnung, wie er in der AVR223 von 2001 noch beschrieben ist, neigt auf Grund der endlichen Genauigkeit der Koeffizienten eher zum Schwingen.&lt;br /&gt;
&lt;br /&gt;
===Software zur Koeffizientenberechnung===&lt;br /&gt;
Es gibt einige spezialisierte Programme, die aber nur eine kleine Anzahl von Digitalfilterkonfigurationen kennen, z.&amp;amp;nbsp;B. [http://www.nuhertz.com/filter/ FilterFree]. Wesentlich universeller sind umfangreiche Programmpakete für numerische Mathematik.&lt;br /&gt;
Neben dem kommerziellen [http://www.mathworks.de Matlab] das auch in einer eingeschränkten Studentenversion angeboten wird, und zu dem zahlreiche Literatur existiert, z.&amp;amp;nbsp;B. ISBN 9783486584271 , gibt es auch zwei kostenlose Nachahmer: [http://www.octave.org Octave] und [http://www.scilab.org Scilab]. Spezialitäten der digitalen Signalverarbeitung bilden nur einen kleinen Teil des Gesamtpakets, und die Hilfetexte dazu sind sehr knapp oder auch mal ein Jahrzehnt alt. Zum Glück sind beide Programme dem Vorbild so nahe, daß man vieles der Literatur zu Matlab entnehmen kann.&lt;br /&gt;
Die eigentliche Koeffizientenberechnung besteht meistens aus nur wenigen Textzeilen. Man gibt wie beim analogen Filter die gewünschten Durchlaß- und Sperrfrequenzen, die Filtercharakteristik und Ordnung ein. Auf eine grafische Benutzeroberfläche muß man allerdings verzichten. Immerhin können der Frequenzgang und andere Kurven grafisch ausgegeben werden.&lt;br /&gt;
&lt;br /&gt;
===Transformationen und komplexe Zahlen===&lt;br /&gt;
Die mathematischen Grundbegriffe der Digitalfilterberechnung sollen hier nur stichwortartig erwähnt werden:&lt;br /&gt;
&lt;br /&gt;
Von der &#039;&#039;Fourier-Transformation&#039;&#039; hat man schon mal gehört, ihre Bedeutung ist noch einigermaßen begreifbar. Von einem periodischen Signal x(t) wie es das Oszilloskop zeigt, also im &#039;&#039;Zeitbereich&#039;&#039;, gelangt man über sie zur spektralen Darstellung x(f) im &#039;&#039;Frequenzbereich&#039;&#039; auf dem Spektrumanalysator. &lt;br /&gt;
Das ist aber nur die halbe Information, eigentlich gehört zu jeder Harmonischen außer der angezeigten Amplitude auch noch ihre Phasenlage. &lt;br /&gt;
x(f) ist also eine zweidimensionale Variable, Amplitude (Betrag) und Phase (Winkel) sind polare Koordinaten. Wenn wir zu kartesischen Koordinaten übergehen, und die x- Achse als &#039;&#039;reelle&#039;&#039;, die y-Achse als &#039;&#039;imaginäre&#039;&#039; Achse bezeichnen, kommen wir zur komplexen Zahlendarstellung.&lt;br /&gt;
Für die Berechnung analoger Filter ist die &#039;&#039;Laplace-Transformation&#039;&#039; zuständig, für digitale Filter die nahe verwandte &#039;&#039;z-Transformation&#039;&#039;. Im ersten Fall wird x(t) in ein X(s) transformiert, in unserem Fall, wie der Name schon sagt in ein X(z). Zur besseren Unterscheidung wird das X groß geschrieben. Auch hier rechnen wir mit komplexen Zahlen, wir befinden uns nach der Transformation in der komplexen &#039;&#039;z-Ebene&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Übertragungsfunktion und Koeffizienten===&lt;br /&gt;
Das Digitalfilter ist für uns zunächst ein schwarzer Kasten, in den ein Signal x(t) hineinläuft und als gefiltertes Signal y(t) wieder herauskommt. Die z-transformierten Signale heißen X(z) und Y(z). Der Quotient Y(z)/X(z) = H(z) wird &#039;&#039;Übertragungsfunktion&#039;&#039;, engl. &#039;&#039;transfer function&#039;&#039; genannt. Für bestimmte Werte von z wird der Zähler oder Nenner der Übertragungsfunktion Null, diese heißen &#039;&#039;Nullstellen&#039;&#039; und &#039;&#039;Pole&#039;&#039; der Funktion. Diese Werte der komplexen Zahl z können im &#039;&#039;Pol/Nullstellendiagramm&#039;&#039; als Punkte in der z-Ebene dargestellt werden, das hilft beispielsweise bei der Untersuchung der &#039;&#039;Stabilität&#039;&#039; des Filters gegen Schwingneigung.&lt;br /&gt;
&lt;br /&gt;
Die genannten Mathematikprogramme berechnen uns aus den gewünschten Filterdaten die Übertragungsfunktion. Im einfachsten Fall können wir daraus die Zahlenwerte direkt in die Filtersoftware als Koeffiziententabelle eintragen. Die Aufteilung in Teilfilter macht die Berechnung etwas umständlicher. Die einzelnen Übertragungsfunktionen werden multipliziert, also Y(z)/X(z) = H&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;(z)*H&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;(z)*H&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;(z). Wir müssen also H(z) in geeignete Faktoren zerlegen, auch dabei hilft uns die Mathematiksoftware.&lt;br /&gt;
&lt;br /&gt;
===Octave und Scilab===&lt;br /&gt;
Am besten installieren wir gleich beide Softwarepakete. Beide bieten unterschiedliche Lösungswege zur Berechnung der gewünschten SOS-Teilfilter.&lt;br /&gt;
In Scilab werden Frequenzen als Bruchteile der Abtastfrequenz, engl. &#039;&#039;sample rate&#039;&#039; des Analog-Digitalwandlers angegeben. Der AD-Wandler im ATmega wird hier mit einer Taktfrequenz von 1/64 des Quarzoszillators betrieben und braucht pro Wandlung 13 Takte. Mit einem 15 MHz – Quarz ergibt sich also ein Abtastfrequenz von 15MHz/(64*13) = 18029 Hz. Octave rechnet mit Bruchteilen der halben Abtastfrequenz, auch &#039;&#039;Nyquist-Frequenz&#039;&#039; genannt.&lt;br /&gt;
Die Filterordnung bezieht sich in beiden Programmen auf Tief- und Hochpassfilter. Für Bandpässe und -sperren muß die Hälfte angegeben werden, hier also 3 statt 6.&lt;br /&gt;
&lt;br /&gt;
Beginnen wir mit Scilab. Das kurze Programm in Bild 1 speichern wir als Textdatei z.&amp;amp;nbsp;B. unter „Sperrfilter1750Hz.sci“ ab, dann lädt es durch Anklicken direkt in den bunten Scilab-Editor und wird mit „Ausführen – in Scilab laden“ gestartet. Ein neues Fenster mit der Frequenzgangkurve öffnet sich und im Scilab-Hauptfenster stehen die Übertragungsfunktionen der drei Teilfilter, sowie die Gesamtverstärkung gain. Die Filterordnung kann nicht direkt vorgegeben werden, wir müssen die vier Grenzfrequenzen und die beiden Dämpfungswerte variieren bis genau drei SOS-Teilfilter herauskommen.&lt;br /&gt;
In Octave werden nur zwei Grenzfrequenzen verlangt, dafür können wir die Filterordnung vorgeben. Wieder wird eine Textdatei ausgeführt und liefert Übertragungsfunktionen für drei Teilfilter.&lt;br /&gt;
&lt;br /&gt;
Einen Schönheitsfehler haben die berechneten Funktionen noch. In der Regelungstechnik und auch in Scilab/Octave wird mit positiven Exponenten von z gerechnet, die Literatur zur digitalen Signalverarbeitung benutzt dagegen negative. Wenn wir aber Zähler und Nenner jeder Teil-Übertragungsfunktion durch z&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; teilen, ändert sie sich nicht und wir haben die Formel wie sie für digitale Filter üblich ist.&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir die Koeffizienten direkt aus den Übertragungsfunktionen ablesen. Wir müssen sie noch &#039;&#039;skalieren&#039;&#039;, also mit einer geeigneten Zweierpotenz multiplizieren und zu einer ganzen Zahl auf/abrunden. Sie sollen hier zu einer 16 Bit-Zahl (Festkommadarstellung mit Vorzeichenbit) werden, also alle Koeffizienten im Bereich -32768...+32767 liegen.&lt;br /&gt;
&lt;br /&gt;
===Frequenzgang maßgeschneidert===&lt;br /&gt;
Mit der Funktion &#039;&#039;&#039;yulewalk&#039;&#039;&#039; können wir auch kompliziertere Frequenzgangkurven erreichen. In Octave fehlt sie, drei ähnlich lautende Funktionen haben nichts mit Filtern zu tun. Die gewünschte Funktion wird mit Geradenstücken zwischen beliebigen Kurvenpunkten vorgegeben. Als Beispiel nehmen wir einen Bandpass für SSTV &#039;&#039;slow scan television&#039;&#039;, der 1974 in der &amp;quot;CQ-DL&amp;quot; vorgestellt wurde. Synchronimpuls (1200 Hz) und Bildinformation (1500-2300 Hz) sollen durchgelassen, Störungen außerhalb dieser Bereiche unterdrückt werden.&lt;br /&gt;
Nach längerem Ausprobieren verschiedener Vorgabewerte und Reduktion der Abtastfrequenz auf die Hälfte ergibt sich eine gute Übereinstimmung mit dem Frequenzgang des Originals. Jetzt haben wir eine Übertragungsfunktion 6.Ordnung, die wieder in SOS-Teilfilter zerlegt werden muß. Diese Funktion &#039;&#039;&#039;tf2sos&#039;&#039;&#039; &#039;&#039;transfer function to second order sections&#039;&#039; fehlt in Scilab, deshalb übertragen wir die Zahlen aus Scilab nach  Octave und erhalten so schließlich unsere Koeffizienten.&lt;br /&gt;
&lt;br /&gt;
Es gibt noch weitere Verfahren, um &amp;quot;Wunschfrequenzgänge&amp;quot; zu berechnen: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;prony&#039;&#039;&#039; in Matlab ( in Scilab nicht vorhanden) [http://www.mikrocontroller.net/topic/244886#new hier im Forum erwähnt] - in ISBN 9780792395591 ab Seite 35 steht ein Matlab-m-file dazu,&lt;br /&gt;
und &amp;lt;br&amp;gt; &#039;&#039;&#039;FDLS&#039;&#039;&#039; (frequency domain least square) von Greg Berchin:&lt;br /&gt;
[http://apollo.ee.columbia.edu/spm/external/tipsandtricks/files/TandT_Jan2007.zip Matlab-File und PDFs dazu], &lt;br /&gt;
[http://www.fpgacentral.com/group/dsp/nearest-iir-system-fir-84479/ Diskussion auf fpgacentral.com] [http://www2.units.it/ramponi/teaching/DSP/materiale/Ch5%28x%293e.pdf#page=29 Grundlagenartikel &amp;quot;Precise Filter Design&amp;quot;] Auch als Kapitel 7 in ISBN 9781118316917 oder ? ISBN 9781118278383 (2.Auflage 2012) oder ISBN 9780470131572 (2007) ab Seite 59 zu finden&lt;br /&gt;
&lt;br /&gt;
===Von der Übertragungsfunktion zum Programm===&lt;br /&gt;
&lt;br /&gt;
Unsere SOS-Teilfilter haben jetzt (je nach Vorzeichen der Exponenten) diese Übertragungsfunktion:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H(z)=\frac{b_{2}\cdot z^{-2}+b_{1}\cdot z^{-1}+b_{0}}{a_{2}\cdot z^{-2}+a_{1}*z^{-1}+1} = &lt;br /&gt;
{\frac{b_{2}+b_{1}\cdot z+b_{0}\cdot z^{2}}{a_{2}+a_{1}\cdot z+z^{2}}}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt wird von z-Bereich wieder in den Zeitbereich rücktransformiert. Diese Funktion y(t)= f(x(t))und der dazugehörige Programmablauf wird üblicherweise in Form eines Blockdiagramms dargestellt:&lt;br /&gt;
&lt;br /&gt;
[[Bild:IIR_Block.png]]&lt;br /&gt;
&lt;br /&gt;
Wir sehen drei Blocktypen: ein Verzögerung um einen Sampletakt Δt, Addition mehrere Summanden, und Multiplikationen mit Konstanten, die aus der Übertragungsfunktion abgelesen werden. Spezielle Signalprozessoren enthalten übrigens für die beiden letzteren einen sogenannten MAC &#039;&#039;multiply-accumulate&#039;&#039; Befehl. Im Atmega-Programm wird es in einem Assembler-Macro namens SMAC32 durchgeführt.&lt;br /&gt;
&lt;br /&gt;
===Literatur===&lt;br /&gt;
* Der wichtigste Artikel zur Signalverarbeitung mit Scilab ist [http://elm.eeng.dcu.ie/~ee317/Matlab_Clones/signal.pdf Signal.pdf (1,2MByte) von 1998]. Die dazugehörigen Programme sind etwas schwerer zu finden, hier habe ich sie daher zu [http://www.mikrocontroller.net/wikifiles/8/82/SignalFiles.pdf SignalFiles.pdf (980kB)] zusammengefasst.&lt;br /&gt;
* [http://www.scilab.org/publications/ Bücher zu Scilab] gibt es nur wenige, und diese gehen nicht auf das Thema Signalverarbeitung ein. &lt;br /&gt;
* Für Januar 2010 angekündigt: ISBN 3527407243 oder 9783527407248 &#039;&#039;Signals and Systems Using SCILAB&#039;&#039;, Vorabinfo: [http://www.wiley-vch.de/img/news/Halbjahresvorschau_I_2008.pdf kurzer Verlagstext PDF Seite 33] und bei Google-books.&lt;br /&gt;
* ISBN 9781584502814 (2004) &#039;&#039;Digital signal processing fundamentals&#039;&#039; mit einem sehr kleinen Anhang &amp;quot;Scilab Tutorial&amp;quot;, sehr oberflächlich&lt;br /&gt;
* ISBN 9780817640095 (1999) &#039;&#039;Engineering and scientific computing with Scilab&#039;&#039; mit einem Kapitel zu &amp;quot;Signal Processing&amp;quot;, für den Einstieg in Scilab sehr zu empfehlen. Auch als unveränderter Nachdruck von 2007 noch neu erhältlich.&lt;br /&gt;
&lt;br /&gt;
===Scilab-Berechnung mit eqiir===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Stopband-Filter für 1750 Hz, Samplerate =18029Hz&lt;br /&gt;
// Eckfrequenzen 1400Hz, 1700Hz, 1800 Hz, 2100Hz:&lt;br /&gt;
omega=[2*%pi*(1400/18029),2*%pi*(1700/18029),2*%pi*(1800/18029),2*%pi*(2100/18029)];&lt;br /&gt;
// Maximale Durchgangswelligkeit 0,5 dB&lt;br /&gt;
deltapass = (1-10**(-0.5/20)) ;&lt;br /&gt;
// minimale Sperrband-Dämpfung 50 dB&lt;br /&gt;
deltastop = 10**(-50/20);&lt;br /&gt;
// IIR-Filter berechnen, &amp;quot;stopband&amp;quot;, &amp;quot;elliptic&amp;quot;:&lt;br /&gt;
[sos,gain,zeroes,poles] = eqiir(&#039;sb&#039;,&#039;el&#039;,omega,deltapass,deltastop);&lt;br /&gt;
// Second order sections anzeigen:&lt;br /&gt;
sos&lt;br /&gt;
gain&lt;br /&gt;
//Frequenzgang berechnen und plotten:&lt;br /&gt;
zaehlerprodukt = prod(sos(2));&lt;br /&gt;
nennerprodukt = prod(sos(3));&lt;br /&gt;
frequenzgang = gain*abs(freq(zaehlerprodukt,nennerprodukt,exp(%i*(0:0.01:%pi))));&lt;br /&gt;
// frequenzgang = gain*abs(freq(zaehlerprodukt,nennerprodukt,exp(%i*(0:0.01:%pi))));&lt;br /&gt;
n = prod(size(frequenzgang));&lt;br /&gt;
//plot(20*log(frequenzgang(2:n))/log(10),(n*18029/(200*%pi)));&lt;br /&gt;
plot(20*log(frequenzgang (2:n))/log(10))&lt;br /&gt;
&lt;br /&gt;
(Ergebnis:)&lt;br /&gt;
                            2                             2                           2&lt;br /&gt;
          1 - 1.6219938z + z            1 - 1.6396794z + z           1 - 1.656616z + z&lt;br /&gt;
sos = --------------------------  *  ------------------------  *  -------------------------&lt;br /&gt;
                                2                             2                            2&lt;br /&gt;
      0.9383702 - 1.5100165z + z     0.8466245 - 1.513936z + z    0.9485511 - 1.663563z + z&lt;br /&gt;
&lt;br /&gt;
gain = 0.8683583&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Messung des 1750 Hz-Sperrfilters===&lt;br /&gt;
&lt;br /&gt;
Gemessen mit [http://www.sillanumsoft.org/ &amp;quot;Visual Analyzer&amp;quot;]:&lt;br /&gt;
&lt;br /&gt;
[[Bild:1750HzNotch.png]]&lt;br /&gt;
&lt;br /&gt;
===Frequenzgang-Planung mit Yulewalk===&lt;br /&gt;
Oben das Programm, weitgehend aus dem Hilfetext entnommen, in der Mitte der berechnete Frequenzgang - Messung liegt noch keine vor -, unten rechts die Vorgabe mit Geradenstücken, links die Übertragungsfunktion 6.Ordnung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Yulewalk.png|Massgeschneiderter Frequenzgang mit yulewalk|640px]]&lt;br /&gt;
&lt;br /&gt;
Die Koeffizienten heißen im Zähler von links nach rechts b6...b0 , im Nenner a6...a0, wobei a0 immer =1 ist.&lt;br /&gt;
Hier die Zerlegung in Teilfilter mit Octave:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
B=[0.1211431 0.0379961 -0.0272326 -0.0361440 -0.0041574 -0.0010921 -0.0894734 ];&lt;br /&gt;
A=[1 -1.7641816 2.7032943 -2.3805502 1.8419165 -0.8344276 0.2958684];         &lt;br /&gt;
[sos,g] = tf2sos(B,A)&lt;br /&gt;
//&lt;br /&gt;
// octave.exe:2&amp;gt; B=[0.1211431 0.0379961 -0.0272326 -0.0361440 -0.0041574 -0.0010921 -0.0894734 ];&lt;br /&gt;
// octave.exe:3&amp;gt; A=[1 -1.7641816 2.7032943 -2.3805502 1.8419165 -0.8344276 0.2958684];&lt;br /&gt;
// octave.exe:4&amp;gt; [sos,g] = tf2sos(B,A)&lt;br /&gt;
// sos =&lt;br /&gt;
//&lt;br /&gt;
//   1.0000000   1.1503168   1.0001280   1.0000000   0.0596667   0.7154071&lt;br /&gt;
//   1.0000000  -0.8390889   0.7389315   1.0000000  -0.7453174   0.7120574&lt;br /&gt;
//   1.0000000   0.0024186  -0.9993911   1.0000000  -1.0785309   0.5808050&lt;br /&gt;
//&lt;br /&gt;
// g =  0.12114&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In drei Zeilen untereinander die drei Teilfilter-Koeffizienten, von links nach rechts b0, b1, b2, a0 (wieder=1), a1 und a2.&lt;br /&gt;
&lt;br /&gt;
===Quelltext des ATmega48-Programms===&lt;br /&gt;
basierend auf AVR223, zerlegt in 3 SOS-Teilfilter, mit Überlaufbegrenzung &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
;***************************************************************************&lt;br /&gt;
;* Digital filter with ATmega48P   6th-order IIR, AVR223 application note  *&lt;br /&gt;
;* 15 MHz xtal, input ADC0, PWM-output OCR1a/b, test output PD0            *&lt;br /&gt;
;* Christoph Kessler 2008                         db1uq_at_t-online_dot_de *&lt;br /&gt;
;***************************************************************************&lt;br /&gt;
.nolist&lt;br /&gt;
.include &amp;quot;m48pdef.inc&amp;quot;&lt;br /&gt;
.list&lt;br /&gt;
;***************************************************************************&lt;br /&gt;
;* register 0-15 (no &amp;quot;immediate&amp;quot;-operations possible):&lt;br /&gt;
;***************************************************************************&lt;br /&gt;
.def	MltLo	= r0	; multiplier result&lt;br /&gt;
.def	MltHi	= r1	; multiplier result&lt;br /&gt;
.def	Zero	= r2	; Zero register (used to add carry flag)&lt;br /&gt;
.def	SavSrg	= r3	; save status register during interrupt routine&lt;br /&gt;
.def	reg04	= r4	; free&lt;br /&gt;
.def	reg05	= r5	; free&lt;br /&gt;
.def	reg06	= r6	; free&lt;br /&gt;
.def	reg07	= r7	; free&lt;br /&gt;
.def	reg08	= r8	; free&lt;br /&gt;
.def	reg09	= r9	; free&lt;br /&gt;
.def	reg10	= r10	; free&lt;br /&gt;
.def	reg11	= r11	; free&lt;br /&gt;
.def	reg12	= r12	; free&lt;br /&gt;
.def	accu0	= r13	; Accumulator - 32bit for Interrupt routine&lt;br /&gt;
.def	accu1	= r14	; Accumulator - 32bit for Interrupt routine&lt;br /&gt;
.def	accu2	= r15	; Accumulator - 32bit for Interrupt routine&lt;br /&gt;
;***************************************************************************&lt;br /&gt;
;* register 16-23 (&amp;quot;immediate&amp;quot;-operations possible):&lt;br /&gt;
;***************************************************************************&lt;br /&gt;
.def	accu3	= r16	; Accumulator - 32bit for Interrupt routine&lt;br /&gt;
.def	reg17	= r17	; free&lt;br /&gt;
.def	reg18	= r18	; free&lt;br /&gt;
.def	reg19	= r19	; free&lt;br /&gt;
.def	datal	= r20	; Data samples mul register&lt;br /&gt;
.def	datah	= r21	;  for Interrupt routine&lt;br /&gt;
.def	coefl	= r22	; Filter coefficient mul register&lt;br /&gt;
.def	coefh	= r23	;  for Interrupt routine&lt;br /&gt;
;***************************************************************************&lt;br /&gt;
;* register 24-31    (16Bit-registers) &lt;br /&gt;
;***************************************************************************&lt;br /&gt;
.def	Tmp1	= r24	; general temporary register&lt;br /&gt;
.def	Tmp2	= r25	; general temporary register&lt;br /&gt;
;	XL	= r26	; free&lt;br /&gt;
;	XH	= r27	; free&lt;br /&gt;
;	YL	= r28	; used by Interrupt routine&lt;br /&gt;
;	YH	= r29	; used by Interrupt routine&lt;br /&gt;
;	ZL	= r30	; init routine only, free for main program&lt;br /&gt;
;	ZH	= r31	; init routine only, free for main program&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* constants :&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
; 1st SOS filter&lt;br /&gt;
.equ 	x11	= 0&lt;br /&gt;
.equ 	x21	= 2&lt;br /&gt;
.equ 	y11	= 4&lt;br /&gt;
.equ 	y21	= 6&lt;br /&gt;
; 2nd SOS filter&lt;br /&gt;
.equ 	x12	= 8&lt;br /&gt;
.equ 	x22	= 10&lt;br /&gt;
.equ 	y12	= 12&lt;br /&gt;
.equ 	y22	= 14&lt;br /&gt;
; 3rd SOS filter&lt;br /&gt;
.equ 	x13	= 16&lt;br /&gt;
.equ 	x23	= 18&lt;br /&gt;
.equ 	y13	= 20&lt;br /&gt;
.equ 	y23	= 22&lt;br /&gt;
; 1st SOS filter&lt;br /&gt;
.equ 	b01	= 24&lt;br /&gt;
.equ 	b11	= 26&lt;br /&gt;
.equ 	b21	= 28&lt;br /&gt;
.equ 	a11	= 30&lt;br /&gt;
.equ 	a21	= 32&lt;br /&gt;
; 2nd SOS filter&lt;br /&gt;
.equ 	b02	= 34&lt;br /&gt;
.equ 	b12	= 36&lt;br /&gt;
.equ 	b22	= 38&lt;br /&gt;
.equ 	a12	= 40&lt;br /&gt;
.equ 	a22	= 42&lt;br /&gt;
; 3rd SOS filter&lt;br /&gt;
.equ 	b03	= 44&lt;br /&gt;
.equ 	b13	= 46&lt;br /&gt;
.equ 	b23	= 48&lt;br /&gt;
.equ 	a13	= 50&lt;br /&gt;
.equ 	a23	= 52&lt;br /&gt;
;*****************************************************&lt;br /&gt;
;* Macros&lt;br /&gt;
;*****************************************************&lt;br /&gt;
.MACRO load_node&lt;br /&gt;
	ldd	datal,Y+@0	; Load low byte of node &lt;br /&gt;
	ldd	datah,Y+@0+1	; Load high byte of node&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
.MACRO update_node&lt;br /&gt;
	std	Y+@0,datal	; Update low byte of node to prepare next filter run&lt;br /&gt;
	std	Y+@0+1,datah	; Update high byte of node to prepare next filter run&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
.MACRO load_coef&lt;br /&gt;
	ldd	coefl,Y+@0	; Load low byte of node &lt;br /&gt;
	ldd	coefh,Y+@0+1	; Load high byte of node&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
.MACRO mul_move_32&lt;br /&gt;
	muls	coefh,datah	; Signed multiply, coefficient high byte and data high byte&lt;br /&gt;
	mov     accu2,MltLo	; Copy result word into accumulator byte 2:3&lt;br /&gt;
	mov     accu3,MltHi	; Copy result word into accumulator byte 2:3&lt;br /&gt;
	mul	coefl,datal	; Unsigned multiply, coefficient low byte and data low byte&lt;br /&gt;
	mov	accu0,MltLo	; Copy result word into accumulator byte 2:3&lt;br /&gt;
	mov	accu1,MltHi	; Copy result word into accumulator byte 2:3&lt;br /&gt;
	mulsu	coefh,datal	; Signed-unsigned multiply, coefficient high byte and data low byte&lt;br /&gt;
	sbc	accu3,Zero	; Sign extention&lt;br /&gt;
	add	accu1,MltLo	; Add low byte of result to accumulator byte 1&lt;br /&gt;
	adc	accu2,MltHi	; Add with carry high byte of result to accumulator byte 2&lt;br /&gt;
	adc	accu3,Zero	; Add carry to accumulator byte 3&lt;br /&gt;
	mulsu	datah,coefl	; Signed-unsigned multiply, data high byte and coefficient low byte&lt;br /&gt;
	sbc	accu3,Zero	; Sign extention&lt;br /&gt;
	add	accu1,MltLo	; Add low byte of result to accumulator byte 1&lt;br /&gt;
	adc	accu2,MltHi	; Add with carry high byte of result to accumulator byte 2&lt;br /&gt;
	adc	accu3,Zero	; Add carry to accumulator byte 3&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
.MACRO smac32&lt;br /&gt;
	muls	coefh,datah	; Signed multiply, coefficient high byte and data high byte&lt;br /&gt;
	add	accu2,MltLo	; Add low byte of result to accumulator byte 2&lt;br /&gt;
	adc	accu3,MltHi	; Add with carry high byte of result to accumulator byte 3&lt;br /&gt;
	mul	coefl,datal	; Unsigned multiply, coefficient low byte and data low byte&lt;br /&gt;
	add	accu0,MltLo	; Add low byte of result to accumulator byte 0&lt;br /&gt;
	adc	accu1,MltHi	; Add with carry high byte of result to accumulator byte 1&lt;br /&gt;
	adc	accu2,Zero	; Add carry to accumulator byte 2&lt;br /&gt;
	adc	accu3,Zero	; Add carry to accumulator byte 3&lt;br /&gt;
	mulsu	coefh,datal	; Signed-unsigned multiply, coefficient high byte and data low byte &lt;br /&gt;
	sbc	accu3,Zero	; Sign extention&lt;br /&gt;
	add	accu1,MltLo	; Add low byte of result to accumulator byte 1&lt;br /&gt;
	adc	accu2,MltHi	; Add with carry high byte of result to accumulator byte 2&lt;br /&gt;
	adc	accu3,Zero	; Add carry to accumulator byte 3&lt;br /&gt;
	mulsu	datah,coefl 	; Signed-unsigned multiply, data high byte and coefficient low byte&lt;br /&gt;
	sbc	accu3,Zero	; Sign extention&lt;br /&gt;
	add	accu1,MltLo	; Add low byte of result to accumulator byte 1&lt;br /&gt;
	adc	accu2,MltHi	; Add with carry high byte of result to accumulator byte 2&lt;br /&gt;
	adc	accu3,Zero	; Add carry to accumulator byte 3&lt;br /&gt;
;	ret&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
.LISTMAC&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* reset/interrupt-vectors:&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
.cseg&lt;br /&gt;
	rjmp	Initial		; after RESET to main program&lt;br /&gt;
	reti			; External Interrupt Request 0&lt;br /&gt;
	reti			; External Interrupt Request 1&lt;br /&gt;
;	reti			; External Interrupt Request 2   mega644&lt;br /&gt;
	reti			; Pin Change Interrupt Request 0&lt;br /&gt;
	reti			; Pin Change Interrupt Request 1&lt;br /&gt;
	reti			; Pin Change Interrupt Request 2&lt;br /&gt;
;	reti			; Pin Change Interrupt Request 3 mega644&lt;br /&gt;
	reti			; Watchdog Time-out Interrupt&lt;br /&gt;
	reti			; Timer/Counter2 Compare Match A&lt;br /&gt;
	reti			; Timer/Counter2 Compare Match B&lt;br /&gt;
	reti			; Timer/Counter2 Overflow&lt;br /&gt;
	reti			; Timer/Counter1 Capture Event&lt;br /&gt;
	reti			; Timer/Counter1 Compare Match A&lt;br /&gt;
	reti			; Timer/Counter1 Compare Match B&lt;br /&gt;
	reti			; Timer/Counter1 Overflow&lt;br /&gt;
	reti			; Timer/Counter0 Compare Match A&lt;br /&gt;
	reti			; Timer/Counter0 Compare Match B&lt;br /&gt;
	reti			; Timer/Counter0 Overflow&lt;br /&gt;
	reti			; SPI Serial Transfer Complete&lt;br /&gt;
	reti			; USART0, Rx Complete&lt;br /&gt;
	reti			; USART0 Data register Empty&lt;br /&gt;
	reti			; USART0, Tx Complete&lt;br /&gt;
;	reti			; Analog Comparator 		 mega644&lt;br /&gt;
	rjmp	ADCint		; ADC Conversion Complete&lt;br /&gt;
	reti			; EEPROM Ready   &lt;br /&gt;
	reti			; 2-wire Serial Interface&lt;br /&gt;
	reti			; Store Program Memory Read&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* after reset: initialise stack,ports&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
Initial: &lt;br /&gt;
	ldi	Tmp1,Low(RAMEND)&lt;br /&gt;
	out	SPL,Tmp1	;&lt;br /&gt;
	ldi	Tmp1,High(RAMEND)&lt;br /&gt;
	out	SPH,Tmp1	; stack initialised&lt;br /&gt;
	clr	Zero		; always Zero&lt;br /&gt;
	ldi	Tmp1,$FF	; &lt;br /&gt;
	out	PortB,Tmp1	; PortB = % 1111 1111&lt;br /&gt;
	out	PortC,Zero	; PortC = % 0000 0000&lt;br /&gt;
	out	PortD,Tmp1	; PortD = % 1111 1111&lt;br /&gt;
	out	DDRB,Tmp1	; PortB direction = % 1111 1111&lt;br /&gt;
	out	DDRC,Zero	; PortC direction = % 0000 0000&lt;br /&gt;
	out	DDRD,Tmp1	; PortD direction = % 1111 1111&lt;br /&gt;
	ldi	Tmp1,$A1	; pos. outputs, fast PWM 8Bit&lt;br /&gt;
	sts	TCCR1A,Tmp1	;&lt;br /&gt;
	ldi	Tmp1,$09	; fast PWM 8Bit, clk/1 (no prescaling)&lt;br /&gt;
	sts	TCCR1B,Tmp1	;&lt;br /&gt;
	sts	OCR1AH,Zero	;&lt;br /&gt;
	sts	OCR1AL,Zero	;&lt;br /&gt;
	sts	OCR1BH,Zero	;&lt;br /&gt;
	sts	OCR1BL,Zero	;&lt;br /&gt;
	ldi	Tmp1,$40	; Ref=Vcc, right-adj, ADC0=input&lt;br /&gt;
	sts	ADMUX,Tmp1	;&lt;br /&gt;
;	ldi	Tmp1,$EE	; Start,Auto, enable Int, Clk/64&lt;br /&gt;
	ldi	Tmp1,$EF	; Start,Auto, enable Int, Clk/128&lt;br /&gt;
	sts	ADCSRA,Tmp1	;&lt;br /&gt;
	ldi	Tmp1,$00	; free running&lt;br /&gt;
	sts	ADCSRB,Tmp1	;&lt;br /&gt;
	ldi	Tmp1,$01	; disable ADC0 dig.inp (optional)&lt;br /&gt;
	sts	DIDR0,Tmp1	;&lt;br /&gt;
	ldi	ZL,low(CoTblF&amp;lt;&amp;lt;1)	; move filter coefficents&lt;br /&gt;
	ldi	ZH,high(CoTblF&amp;lt;&amp;lt;1)	; from program-flash&lt;br /&gt;
	ldi	YL,low(CoTblS)	; to SRAM&lt;br /&gt;
	ldi	YH,high(CoTblS)	;&lt;br /&gt;
	ldi	Tmp1,30		; count 15 * 16 Bit coefficients&lt;br /&gt;
TbLoop:&lt;br /&gt;
	lpm	Tmp2,Z+		; fetch 1 byte from coefficient table&lt;br /&gt;
	st	Y+,Tmp2		; copy coefficient to Sram, increment Y&lt;br /&gt;
	dec	Tmp1&lt;br /&gt;
	brne	TbLoop&lt;br /&gt;
	ldi	YL,low(DatTbl)	; load SRAM-Pointer for Interrupt routine&lt;br /&gt;
	ldi	YH,high(DatTbl)	;&lt;br /&gt;
	sei			; enable interrupts&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* Main program:&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
Endless:&lt;br /&gt;
	rjmp	Endless		; &lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* ADC-Interrupt routine: compute filter and update PWM output&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
ADCint:&lt;br /&gt;
	sbi	PortD,0		; just to measure INT-Time&lt;br /&gt;
	in	SavSrg,SREG	; save status register&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* 1st SOS filter&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
	load_coef 	b21	; b21*x1[t-2]&lt;br /&gt;
	load_node 	x21	; &lt;br /&gt;
	mul_move_32		; &lt;br /&gt;
	load_coef 	b11	; b11*x1[t-1]&lt;br /&gt;
	load_node	x11	; &lt;br /&gt;
	update_node 	x21	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	b01	; b01*x1[t]&lt;br /&gt;
	lds	datal,ADCL	; Load new sample &lt;br /&gt;
	lds	datah,ADCH	; into data multiply register&lt;br /&gt;
	dec	datah		; convert 10 bit unsigned $03FF -&amp;gt; $01FF&lt;br /&gt;
	dec	datah		; to 16 Bit signed        $0000 -&amp;gt; $FE00&lt;br /&gt;
&lt;br /&gt;
	lsl	datal&lt;br /&gt;
	rol	datah&lt;br /&gt;
	lsl	datal&lt;br /&gt;
	rol	datah&lt;br /&gt;
	lsl	datal&lt;br /&gt;
	rol	datah&lt;br /&gt;
	lsl	datal&lt;br /&gt;
	rol	datah&lt;br /&gt;
	lsl	datal&lt;br /&gt;
	rol	datah&lt;br /&gt;
	lsl	datal&lt;br /&gt;
	rol	datah&lt;br /&gt;
&lt;br /&gt;
	update_node 	x11	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	a21	; a21*y1[t-2]&lt;br /&gt;
	load_node 	y21	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	a11	; a11*y1[t-1]&lt;br /&gt;
	load_node 	y11	; &lt;br /&gt;
	update_node 	y21	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	cpi	accu3,$20	; accu &amp;lt;   $20000000 ?&lt;br /&gt;
	brlo	NoLimit1	;&lt;br /&gt;
	cpi	accu3,-$20	; accu &amp;gt;= -$20000000 ?&lt;br /&gt;
	brsh	NoLimit1	;&lt;br /&gt;
	clr	accu2		; accu2 = $00&lt;br /&gt;
	cpi	accu3,0		;&lt;br /&gt;
	brge	PosLim1		; &lt;br /&gt;
	ldi	accu3,$80	; accu3 = $80&lt;br /&gt;
	rjmp	Limit1		; &lt;br /&gt;
PosLim1:&lt;br /&gt;
	ldi	accu3,$7F	; accu3 = $7F	&lt;br /&gt;
	com	accu2		; accu2 = $FF	&lt;br /&gt;
	rjmp	Limit1		; &lt;br /&gt;
NoLimit1:&lt;br /&gt;
	lsl	accu1		; Scaling to gain factor 2^15&lt;br /&gt;
	rol	accu2		; &lt;br /&gt;
	rol	accu3		; &lt;br /&gt;
	lsl	accu1		; Scaling to gain factor 2^16&lt;br /&gt;
	rol	accu2		; &lt;br /&gt;
	rol	accu3		; &lt;br /&gt;
Limit1:&lt;br /&gt;
	std	Y+y11,accu2	; Updating y1[t-1] node to prepare next filter run &lt;br /&gt;
	std	Y+y11+1,accu3	; and save it for following SOS filter&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* 2nd SOS filter&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
	load_coef 	b22	; b22*x2[t-2]&lt;br /&gt;
	load_node 	x22	; &lt;br /&gt;
	mul_move_32		; &lt;br /&gt;
	load_coef 	b12	; b12*x2[t-1]&lt;br /&gt;
	load_node	x12	; &lt;br /&gt;
	update_node 	x22	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	b02	; b02*x2[t]&lt;br /&gt;
	load_node 	y11	; result of 1st SOS&lt;br /&gt;
	update_node 	x12	; &lt;br /&gt;
	smac32			;  &lt;br /&gt;
	load_coef 	a22	; a22*y2[t-2]&lt;br /&gt;
	load_node 	y22	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	a12	; a12*y2[t-1]&lt;br /&gt;
	load_node 	y12	; &lt;br /&gt;
	update_node 	y22	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	cpi	accu3,$20	; accu &amp;lt;   $20000000 ?&lt;br /&gt;
	brlo	NoLimit2	;&lt;br /&gt;
	cpi	accu3,-$20	; accu &amp;gt;= -$20000000 ?&lt;br /&gt;
	brsh	NoLimit2	;&lt;br /&gt;
	clr	accu2		; accu2 = $00&lt;br /&gt;
	cpi	accu3,0		;&lt;br /&gt;
	brge	PosLim2		; &lt;br /&gt;
	ldi	accu3,$80	; accu3 = $80&lt;br /&gt;
	rjmp	Limit2		; &lt;br /&gt;
PosLim2:&lt;br /&gt;
	ldi	accu3,$7F	; accu3 = $7F	&lt;br /&gt;
	com	accu2		; accu2 = $FF	&lt;br /&gt;
	rjmp	Limit2		; &lt;br /&gt;
NoLimit2:&lt;br /&gt;
	lsl	accu1		; Scaling to gain factor 2^15&lt;br /&gt;
	rol	accu2		; &lt;br /&gt;
	rol	accu3		; &lt;br /&gt;
	lsl	accu1		; Scaling to gain factor 2^16&lt;br /&gt;
	rol	accu2		; &lt;br /&gt;
	rol	accu3		; &lt;br /&gt;
Limit2:&lt;br /&gt;
	std	Y+y12,accu2	; Updating y2[t-1] node to prepare next filter run &lt;br /&gt;
	std	Y+y12+1,accu3	; and save it for following SOS filter&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* 3rd SOS filter&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
	load_coef 	b23	; b23*x3[t-2]&lt;br /&gt;
	load_node 	x23	; &lt;br /&gt;
	mul_move_32		; &lt;br /&gt;
	load_coef 	b13	; b13*x3[t-1]&lt;br /&gt;
	load_node	x13	; &lt;br /&gt;
	update_node 	x23	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	b03	; b03*x3[t]&lt;br /&gt;
	load_node 	y12	; result of 2nd SOS&lt;br /&gt;
	update_node 	x13	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	a23	; a23*y3[t-2]&lt;br /&gt;
	load_node 	y23	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	load_coef 	a13	; a13*y3[t-1]&lt;br /&gt;
	load_node 	y13	; &lt;br /&gt;
	update_node 	y23	; &lt;br /&gt;
	smac32			; &lt;br /&gt;
	cpi	accu3,$20	; accu &amp;lt;   $20000000 ?&lt;br /&gt;
	brlo	NoLimit3	;&lt;br /&gt;
	cpi	accu3,-$20	; accu &amp;gt;= -$20000000 ?&lt;br /&gt;
	brsh	NoLimit3	;&lt;br /&gt;
	clr	accu2		; accu2 = $00&lt;br /&gt;
	cpi	accu3,0		;&lt;br /&gt;
	brge	PosLim3		; &lt;br /&gt;
	ldi	accu3,$80	; accu3 = $80&lt;br /&gt;
	rjmp	Limit3		; &lt;br /&gt;
PosLim3:&lt;br /&gt;
	ldi	accu3,$7F	; accu3 = $7F	&lt;br /&gt;
	com	accu2		; accu2 = $FF	&lt;br /&gt;
	rjmp	Limit3		; &lt;br /&gt;
NoLimit3:&lt;br /&gt;
	lsl	accu1		; Scaling to gain factor 2^15&lt;br /&gt;
	rol	accu2		; &lt;br /&gt;
	rol	accu3		; &lt;br /&gt;
	lsl	accu1		; Scaling to gain factor 2^16&lt;br /&gt;
	rol	accu2		; &lt;br /&gt;
	rol	accu3		; &lt;br /&gt;
Limit3:&lt;br /&gt;
	std	Y+y13,accu2	; Updating y3[t-1] node to prepare next filter run &lt;br /&gt;
	std	Y+y13+1,accu3	; &lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* PWM - D/A-output&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
	subi	accu3,$80	; signed to unsigned  $8000 -&amp;gt;$0000, $7FFF -&amp;gt;$FFFF&lt;br /&gt;
	sts	OCR1AH,Zero	; &lt;br /&gt;
	sts	OCR1AL,Tmp1	; fast PWM 8 bit input signal to OCR1A&lt;br /&gt;
	sts	OCR1BH,Zero	; &lt;br /&gt;
	sts	OCR1BL,accu3	; fast PWM 8 bit result to OCR1B&lt;br /&gt;
	cbi	PortD,0		; just to measure INT-Time&lt;br /&gt;
	out	SREG,SavSrg	; restore status register&lt;br /&gt;
	reti			; &lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* coefficient table in flash memory&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
CoTblF:&lt;br /&gt;
/* &lt;br /&gt;
;1750 Hz Sperrfilter:&lt;br /&gt;
	.dw 	16384	 	;  b01 *16384 ( 1        )&lt;br /&gt;
	.dw 	-26575	 	;  b11 *16384 (-1,6219938)&lt;br /&gt;
	.dw 	16384	 	;  b21 *16384 ( 1        )&lt;br /&gt;
	.dw 	24740		; -a11 *16384 ( 1,5100165)&lt;br /&gt;
	.dw 	-15374	 	; -a21 *16384 (-0,9383702)&lt;br /&gt;
&lt;br /&gt;
	.dw 	16384	 	;  b02 *16384 ( 1        )&lt;br /&gt;
	.dw 	-26865	 	;  b12 *16384 (-1,6396794)&lt;br /&gt;
	.dw 	16384	 	;  b22 *16384 ( 1        )&lt;br /&gt;
	.dw 	24804	 	; -a12 *16384 ( 1,5139300)&lt;br /&gt;
	.dw 	-13871	 	; -a22 *16384 (-0,8466245)&lt;br /&gt;
&lt;br /&gt;
	.dw 	16384		;  b03 *16384 ( 1        )&lt;br /&gt;
	.dw 	-27142	 	;  b13 *16384 (-1,6566160)&lt;br /&gt;
	.dw 	16384		;  b23 *16384 ( 1        )&lt;br /&gt;
	.dw 	27256	 	; -a13 *16384 ( 1,6635630)&lt;br /&gt;
	.dw 	-15541	 	; -a23 *16384 (-0,9485511) */&lt;br /&gt;
&lt;br /&gt;
;SSTV-Bandpass nach DJ6HP 015:&lt;br /&gt;
	.dw 	16384	 	;  b01 *16384 ( 1        )&lt;br /&gt;
	.dw 	18847	 	;  b11 *16384 ( 1.1503168)&lt;br /&gt;
	.dw 	16386	 	;  b21 *16384 ( 1.0001280)&lt;br /&gt;
	.dw 	-978		; -a11 *16384 (-0.0596667)&lt;br /&gt;
	.dw 	-11721	 	; -a21 *16384 (-0.7154071)&lt;br /&gt;
&lt;br /&gt;
	.dw 	16384	 	;  b02 *16384 ( 1        )&lt;br /&gt;
	.dw 	-13748	 	;  b12 *16384 (-0.8390889)&lt;br /&gt;
	.dw 	12107	 	;  b22 *16384 ( 0.7389315)&lt;br /&gt;
	.dw 	12211	 	; -a12 *16384 ( 0.7453174&lt;br /&gt;
	.dw 	-11666	 	; -a22 *16384 (-0.7120574)&lt;br /&gt;
;&lt;br /&gt;
	.dw 	16384		;  b03 *16384 ( 1        )&lt;br /&gt;
	.dw 	40	 	;  b13 *16384 ( 0.0024186)&lt;br /&gt;
	.dw 	-16374		;  b23 *16384 (-0.9993911)&lt;br /&gt;
	.dw 	17671	 	; -a13 *16384 ( 1.0785309)&lt;br /&gt;
	.dw 	-9516	 	; -a23 *16384 (-0.5808050)&lt;br /&gt;
&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* data memory in SRAM&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
.dseg&lt;br /&gt;
.org	$0100&lt;br /&gt;
DatTbl:&lt;br /&gt;
	.dw 	$0000 	 	; x11&lt;br /&gt;
	.dw 	$0000 	 	; x21&lt;br /&gt;
	.dw 	$0000 	 	; y11&lt;br /&gt;
	.dw 	$0000 	 	; y21&lt;br /&gt;
;&lt;br /&gt;
	.dw 	$0000 	 	; x12&lt;br /&gt;
	.dw 	$0000 	 	; x22&lt;br /&gt;
	.dw 	$0000 	 	; y12&lt;br /&gt;
	.dw 	$0000 	 	; y22&lt;br /&gt;
;&lt;br /&gt;
	.dw 	$0000 	 	; x13&lt;br /&gt;
	.dw 	$0000 	 	; x23&lt;br /&gt;
	.dw 	$0000 	 	; y13&lt;br /&gt;
	.dw 	$0000 		; y23&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
;* coefficient table in SRAM&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
CoTblS:&lt;br /&gt;
	.dw 	$0000 	 	;  b01 *16384&lt;br /&gt;
	.dw 	$0000 	 	;  b11 *16384&lt;br /&gt;
	.dw 	$0000		;  b21 *16384&lt;br /&gt;
	.dw 	$0000	 	; -a11 *16384&lt;br /&gt;
	.dw 	$0000	 	; -a21 *16384&lt;br /&gt;
;&lt;br /&gt;
	.dw 	$0000	 	;  b02 *16384&lt;br /&gt;
	.dw 	$0000 		;  b12 *16384&lt;br /&gt;
	.dw 	$0000	 	;  b22 *16384&lt;br /&gt;
	.dw 	$0000		; -a12 *16384&lt;br /&gt;
	.dw 	$0000	 	; -a22 *16384&lt;br /&gt;
;&lt;br /&gt;
	.dw 	$0000 		;  b03 *16384&lt;br /&gt;
	.dw 	$0000	 	;  b13 *16384&lt;br /&gt;
	.dw 	$0000		;  b23 *16384&lt;br /&gt;
	.dw 	$0000 		; -a13 *16384&lt;br /&gt;
	.dw 	$0000	 	; -a23 *16384&lt;br /&gt;
;*************************************************************************&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Category:DSP]]&lt;/div&gt;</summary>
		<author><name>46.128.38.250</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Brushless-Controller_f%C3%BCr_Modellbaumotoren&amp;diff=80288</id>
		<title>Brushless-Controller für Modellbaumotoren</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Brushless-Controller_f%C3%BCr_Modellbaumotoren&amp;diff=80288"/>
		<updated>2013-12-30T18:09:17Z</updated>

		<summary type="html">&lt;p&gt;46.128.38.250: /* Einsatz der BEMF */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Im Internet gibt es einige grundlegende Informationen zur Funktionsweise und Ansteuerung von Brushless-Motoren (BLDC). Für die Entwicklung eines solchen Reglers findet man aber nur wenig richtig detaillierte Informationen und Erfahrungsberichte. In diesem Artikel sollen genau diese Lücken geschlossen werden. Es soll hier aber kein fertiges Produkt (Schaltplan + Layout + Software) angeboten werden. Viel mehr soll es die Eigenentwicklung unterstützen, Ideen und Erfahrungen anbieten.&lt;br /&gt;
&lt;br /&gt;
An dieser Stelle weise ich noch darauf hin, dass man bei den [[#Weblinks]] noch einige sehr gute Informationen findet! Es gibt dort Hardware und Software, es lohnt sich die Links mal anzuschauen.&lt;br /&gt;
&lt;br /&gt;
==== Um welche Motoren geht es genau? ====&lt;br /&gt;
&lt;br /&gt;
Es geht hier um die sogenannten elektrisch kommutierten bürstenlosen Gleichstrommotoren (BLDC) aus dem Modellbaubereich. &lt;br /&gt;
&lt;br /&gt;
Deren Eigenschaften sind:&lt;br /&gt;
* Haben drei Anschlüsse für die drei Phasen, ansonsten sind keine weiteren Anschlüsse vorhanden&lt;br /&gt;
* Werden in der Regel mit LiPo oder Nickel Akkus versorgt&lt;br /&gt;
* Leistung im Bereich von ca. 100W bis 2kW&lt;br /&gt;
* Spannungen im Bereich von ca. 7 bis 50V&lt;br /&gt;
* Ströme im Bereich von ca. 5 bis 120A&lt;br /&gt;
&lt;br /&gt;
==== Um welche Motoren geht es hier nicht? ====&lt;br /&gt;
&lt;br /&gt;
* Motoren mit Hallsensoren für die Rückmeldung&lt;br /&gt;
* Festplattenmotoren&lt;br /&gt;
&lt;br /&gt;
Unter Umständen kann aber dieser Artikel auch für solche Motoren nützlich sein.&lt;br /&gt;
&lt;br /&gt;
== Funktionsweise dieser Motoren ==&lt;br /&gt;
&lt;br /&gt;
=== Ansteuerung ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:BLDC_Spannungs_Diagramm.png|thumb|right|250px|Ansteuerung der 3 Phasen]]&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich werden die 3 Phasen nacheinander bestromt, die Phasenspannungen wären also drei um 120° phasenverschobene Rechteckspannungen. Ein sinusförmiger Drehstrom ist nicht nötig, es genügen Rechteckspannungen. Mit einer Raumzeigermodulation könnte man die Stromaufnahme und die Geräuschentwicklung zwar noch verringern, macht die Ansteuerung aber einiges aufwändiger. Sogar die käuflichen Regler arbeiten nur mit Rechtecksignalen, zumindest die die ich kenne. &lt;br /&gt;
&lt;br /&gt;
Dabei gibt es für jede Phase die Zustände „Low“, „High“ und „Floating“. Low bedeutet 0V (GND), High entspricht der Versorgungsspannung und Floating ist keines von beidem, die Phase „hängt in der Luft“. Bei „High“ wird aber noch der Mittelwert der Spannung per PWM eingestellt, über das Tastverhältnis wird schlussendlich die Drehzahl verändert! Dazu aber später mehr.&lt;br /&gt;
&lt;br /&gt;
In der Grafik rechts kann man den Spannungsverlauf sehr gut erkennen. Das Diagramm zeigt aber nur den theoretischen Verlauf der Spannungen, wobei die gestrichelten Linien den Zustand &amp;quot;floating&amp;quot; symbolisieren. Dies kann man in einem Diagramm ja nicht wirklich darstellen, das ist einfach symbolisch gemeint. Interessanterweise sehen die Spannungen aufgrund der BEMF aber tatsächlich ziemlich ähnlich aus wie im Diagramm!&lt;br /&gt;
&lt;br /&gt;
=== Die 6 Zustände ===&lt;br /&gt;
&lt;br /&gt;
Wie man erkennen kann, werden 6 Zustände gebraucht, die sich dann immer wiederholen. Die Kommutierung ist also einfach ein Weiterschalten des Zustandes. &lt;br /&gt;
&#039;&#039;Diese 6 Zustände sind nicht mit den drei Zuständen von oben (High, Low, Floating) zu verwechseln, das ist ein anderes Thema!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In einer Tabelle dargestellt würde das folgendermassen aussehen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Zustand || Phase A || Phase B || Phase C || Stromfluss || Komparator-Eingänge&lt;br /&gt;
|-&lt;br /&gt;
| 1 || PWM || Floating || GND || A --&amp;gt; C || MITTEL &amp;lt;--&amp;gt; NULL_B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Floating || PWM || GND || B --&amp;gt; C || MITTEL &amp;lt;--&amp;gt; NULL_A&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GND || PWM || Floating || B --&amp;gt; A || MITTEL &amp;lt;--&amp;gt; NULL_C&lt;br /&gt;
|-&lt;br /&gt;
| 4 || GND || Floating || PWM || C --&amp;gt; A || MITTEL &amp;lt;--&amp;gt; NULL_B&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Floating || GND || PWM || C --&amp;gt; B || MITTEL &amp;lt;--&amp;gt; NULL_A&lt;br /&gt;
|-&lt;br /&gt;
| 6 || PWM || GND || Floating || A --&amp;gt; B || MITTEL &amp;lt;--&amp;gt; NULL_C&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Hinweise:&lt;br /&gt;
* Die Nummern in der ersten Spalte entsprechen genau den sechs Zuständen, die auch im obigen Diagramm nummeriert sind (Alle 6 Zustände zusammen bilden einen Zyklus, wie es auch im Diagramm dargestellt ist)&lt;br /&gt;
* Den Inhalt der letzten Spalte wird später noch erläutert. Die Bezeichnungen beziehen sich auf die [[#BEMF-Schaltung]].&lt;br /&gt;
&lt;br /&gt;
=== Einsatz der BEMF ===&lt;br /&gt;
Das schaut bis jetzt eigentlich wie ein Synchronmotor oder Schrittmotor aus, was ein BLDC im Prinzip auch ist.&lt;br /&gt;
&lt;br /&gt;
Wie schon erwähnt wurde, wird ein BLDC elektronisch kommutiert. Das heisst, die Kommutierung wird nicht einfach stur vorgegeben, sondern es wird immer Rücksicht auf die Ankerposition genommen. Dazu muss man allerdings wissen, wann man die Kommutierung genau auslösen soll. &lt;br /&gt;
&lt;br /&gt;
Dieses Verfahren heißt Block-Kommutierung und ist ein Kompromiss aus (Regelungs-)Aufwand und Ergebnis:&lt;br /&gt;
Idealerweise werden die Ströme im Stator so eingeprägt, dass der Statorfluss dem Rotorfluss immer um 90° vorauseilt. Nur so wird das ideale Drehmoment erzeugt (siehe Literatur zur permanenterregten Synchronmaschine). Allerdings hat dieses Verfahren, auch Feldorientierte Regelung oder Vektor-Regelung genannt, den Nachteil, dass meistens teure Positionssensorik für den Rotor nowendig ist und auch die nötige Rechenleistung stark ansteigt. Die komplette Regelung muss für jede PWM-Periode gerechnet werden, damit sich der Aufwand lohnt. &lt;br /&gt;
BLDC-Motoren werden deshalb meist explizit so konstruiert, dass sich mit Block-Kommutierung ein konstantes Drehmoment einstellen kann. Der ideale Kommutierungszeitpunkt ist eigentlich ein Kommutierungswinkel, der Kommutierungszeitpunkt unter anderem deshalb drehzahlabhängig.&lt;br /&gt;
&lt;br /&gt;
Zur Erreichung einer höheren Maximaldrehzahl kann das Rotorfeld durch das Statorfeld im sogenannten Feldschwäch-Betrieb geschwächt werden. Es ergeben sich Feldschwäch-(Blind)ströme im Bereich der Nennströme. Die Feldschwächung hat Einfluss auf den Kommutierungszeitpunkt.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich kann auch ein BLDC nicht ohne Kenntnis der Lage des Rotors kommutiert werden. Und hier kommt die sogenannte Back Electromotive Force (BEMF) zum Einsatz. Von den drei Phasen liegt ja zu jedem Zeitpunkt genau eine Phase in der Luft wie man am Diagramm oben erkennen kann. Aufgrund des drehenden Magnetfeldes im Motor wird an dieser Phase nun eine Spannung induziert. Und genau diese induzierte Spannung gibt nun Auskunft darüber, in welchem Winkel sich der Anker befindet, und daraus kann man dann auch den Zeitpunkt der nächsten Kommutierung bestimmen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich wird aber auch noch die Sternmittelpunktspannung der drei Phasen benötigt, welche aber leider nicht direkt zur Verfügung steht. Das ist aber kein Problem, mit drei Widerständen kann man sich die selber erzeugen (siehe [[#BEMF-Schaltung]]).&lt;br /&gt;
&lt;br /&gt;
Jetzt sollten die BEMF-Spannungen die Sternmittelpunktspannung ständig kreuzen, was man dann mit einem Komparator erfassen kann. Und den Interrupt, den der Komparator auslöst, ist nun verantwortlich für die nächste Kommutierung.&lt;br /&gt;
Der Komparator wird natürlich nacheinander mit den drei Phasen gefüttert, es darf immer nur die Phase an den Komparator angeschlossen sein, die auch in der Luft hängt! In der Tabelle [[#Die 6 Zustände]] sieht man, welche zwei Spannungen der Komparator jeweils vergleichen muss.&lt;br /&gt;
&lt;br /&gt;
Als Komparator kann man übrigens den integrierten nehmen, den es in den AVRs gibt. Diese (alle?) haben auch den benötigten Multiplexer, um zwischen den drei Analogquellen wählen zu können. Näheres dazu im Abschnitt [[#Software]].&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Leistungsteil ===&lt;br /&gt;
&lt;br /&gt;
==== Treiber ====&lt;br /&gt;
&lt;br /&gt;
Um die drei notwendigen Zustände (&#039;&#039;Low&#039;&#039;, &#039;&#039;High&#039;&#039; und &#039;&#039;Floating&#039;&#039;) für jede der drei Phasen realisieren zu können, werden drei Halbbrücken mit Mosfets benötigt. Hier gibt es dann auch schon mehrere Varianten, wie man das aufbauen kann. Grundsätzlich muss man sich mal überlegen ob fertige FET-Treiber oder diskrete Treiber verwendet werden sollen. Die FET-Treiber haben einige sehr schöne Vorteile, deshalb sollte man diese meiner Meinung nach bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Die Vorteile wären:&lt;br /&gt;
&lt;br /&gt;
* Integrierter Kurzschlussschutz mit dead time, ein Softwarefehler kann die FETs nicht zerstören. Das kann in der Entwicklungsphase sehr von Vorteil sein :-)&lt;br /&gt;
* Die FETs können mit ordentlicher Geschwindigkeit geschaltet werden, und die Mikrocontroller-Ports werden trotzdem nicht stark belastet. So kann die Wärmeentwicklung der FETs noch etwas reduziert werden.&lt;br /&gt;
* Bei Treibern die mit nur einem Eingang zwischen Lowside und Highside Mosfets toggeln (z.B. IR2104), ist der sogenannte „aktiver Freilauf“ bereits in Hardware realisiert und ermöglicht so mit wenig Aufwand eine extrem niedrige Erwärmung der Mosfets. Das ermöglicht schon sehr grosse Ströme auch ohne Kühlkörper!&lt;br /&gt;
* Es können günstigere Mosfets verwendet werden, es müssen keine TTL-Kompatible FETs sein. Auch ist eine niedrige Gatekapazität nicht so von Bedeutung wie bei direkter Ansteuerung mit einem Mikrocontroller.&lt;br /&gt;
* Je nach dem welchen Treiber man verwendet, kann der Softwareaufwand und die Fehleranfälligkeit deutlich reduziert werden.&lt;br /&gt;
&lt;br /&gt;
Nachteile von Treiber sind:&lt;br /&gt;
&lt;br /&gt;
* Mehr Bauteile auf der Platine.&lt;br /&gt;
* Vermutlich insgesamt etwas teurer, auch wenn die FETs günstiger sind.&lt;br /&gt;
* Bei vielen Treibern ist eine Minimalspannung von ca. 10V notwendig, damit sie funktionieren. Bei einem fast leeren 3S LiPo Akku könnte das vielleicht schon kritisch werden. Auch darf z.B. beim IR2104 eine Spannung von 20V nicht überschritten werden. Daher kommt (ohne StepUp und StepDown Wandler) eigentlich fast nur noch ein 4S Akku in Frage. Möchte man einen grösseren Eingangsspannungsbereich haben muss man noch entsprechende Spannungsregler einbauen.&lt;br /&gt;
&lt;br /&gt;
Ich persönlich habe es schon mit einem IR2104S probiert, dieser erscheint mir sehr geeignet für diese Aufgabe. Ich betreibe ihn mit einem 4S LiPo, damit läuft das Teil perfekt. Kann ich nur weiterempfehlen!&lt;br /&gt;
&lt;br /&gt;
==== Beispielschaltung ====&lt;br /&gt;
[[Datei:BLDC_Leistungsteil_1.png|thumb|right|300px|Beispiel einer Halbbrücke inklusive Strommessung]]&lt;br /&gt;
Hier ein Beispiel, wie der Leistungsteil einer Phase aussehen könnte.&lt;br /&gt;
&lt;br /&gt;
Für die exakte Beschaltung der Treiber muss man natürlich dessen Datenblatt studieren!&lt;br /&gt;
&lt;br /&gt;
Hier sieht man auch gleich noch die Strommessung, die man natürlich nicht für jede Phase einzeln aufbauen muss. Man kann sie sogar ganz weglassen, sie könnte aber nützlich sein um eine Überlast des Motors erkennen zu können.&lt;br /&gt;
&lt;br /&gt;
Der Widerstand R20 ist dazu da, dass auf dem Treiber das PWM-Signal liegt, sobald die Leitung „IN_A“ in der Luft hängt (uC Pin als Eingang definiert). So wird nur ein einziger PWM-Ausgang vom Mikrocontroller benötigt für alle drei Phasen, erfordert also kein Soft-PWM oder sonst irgend ein Murks. Diese Schaltung habe ich übrigens beim Mikrokopter-Projekt abgeschaut.&lt;br /&gt;
&lt;br /&gt;
Übrigens muss an die Versorgung unbedingt noch ein grosser Elko gehängt werden, am besten möglichst nahe an die Mosfets (keine langen Leitungen zwischen Elko und Mosfets). Die erforderliche Kapazität hängt davon ab, wieviel Strom der Motor braucht. bei kleinen bis mittleren Motoren sollten so 220uF bis 680uF ausreichend sein.&lt;br /&gt;
&lt;br /&gt;
=== BEMF-Schaltung ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:BLDC_BEMF_schaltung.png|thumb|right|300px|BEMF-Schaltung]]&lt;br /&gt;
&lt;br /&gt;
Ein wichtiger Teil ist aber auch die BEMF-Schaltung. Dabei wird häufig die Schaltung vom Mikrokopter eingesetzt (siehe Schaltung rechts).&lt;br /&gt;
&lt;br /&gt;
Die Schaltung besteht erstmal aus drei Spannungsteilern, die die Phasenspannungen auf ein Spannungsniveau heruntersetzen, das man auf die Mikrokontrollereingänge legen darf. Keramikkondensatoren glätten diese Spannungen, weil die aufgrund der PWM sonst sehr stark ausschlagen. Dann gehen diese drei Spannungen (&#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039;) auf drei ADC-Eingänge des Mikrocontrollers.&lt;br /&gt;
&lt;br /&gt;
Und dann sind da noch die drei Widerstände, die aus den Spannungen &#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039; einen virtuellen Sternmittelpunkt bilden. Diese Mittelpunktspannung (&#039;&#039;MITTEL&#039;&#039;) kommt dann auf den Komparatoreingang &#039;&#039;AIN0&#039;&#039; vom AVR. Diese Spannung soll der Komparator später dann mit jeweils einer der Spannungen &#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039; vergleichen um den Kommutierungszeitpunkt bestimmen zu können.&lt;br /&gt;
&lt;br /&gt;
Man kann die Widerstands-/ und Kapazitätswerte auch noch anpassen. Bei höheren Eingangsspannungen muss man darauf achten, dass die Eingänge vom AVR keine zu hohe Spannung abkriegen! Ein Regler, den ich gekauft habe, hat einiges höhere Widerstandswerte und kommt sogar ohne Kondensatoren aus. Hier hat man also durchaus noch Spielraum um ein bisschen zu tüfteln, für den Anfang ist die abgebildete Schaltung aber bestens geeignet.&lt;br /&gt;
&lt;br /&gt;
=== Mikrocontroller ===&lt;br /&gt;
&lt;br /&gt;
Als Mikrocontroller sind viele Typen aus der AVR-Serie geeignet. Bei der BrushlessCtrl wird zum Beispiel ein ATMega168 eingesetzt. Mit diesem habe ich auch mal angefangen, der scheint wirklich gut geeignet zu sein. Es reicht aber auch ein ATMega88 wenn man nicht alle möglichen Protokolle und Ansteuerungsarten (I2C, SPI, PPM) gleichzeitig einbauen will.&lt;br /&gt;
&lt;br /&gt;
Viele Regler verwenden auch einen AT90PWM, vorallem wenn mehrere PWM-Kanäle gebraucht werden.&lt;br /&gt;
&lt;br /&gt;
Übrigens wird bei käuflichen Reglern extrem häufig ein ATMega8 eingesetzt! Wenn man nur Software entwickeln möchte kann man auch einen solchen Regler kaufen und das eigene Programm aufspielen. Bei den [[#Weblinks]] findet man dazu auch noch Informationen.&lt;br /&gt;
&lt;br /&gt;
Um eine Raumzeigermodulation zu implementieren wird dann aber vermutlich schon ein 32-Bit Mikrocontroller nötig sein. Aber wie schon erwähnt ist für ein Modellbaumotor eine Raumzeigermodulation keinesfalls ein must-have.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Bei der Software kommt es jetzt natürlich sehr stark darauf an, wie die Hardware aufgebaut ist. Ich möchte hier aber nicht auf jede Variante eingehen, das gäbe viel zu viel Arbeit. Auch will ich ja keinen fertigen Code bereitstellen, sondern nur Hinweise und Tipps geben. Wer nicht selber programmieren will, der kann ja mal die Mikrokopter-Firmware herunterladen, die älteren Versionen davon gibt es auf der Mikrokopter-Seite zum downloaden.&lt;br /&gt;
&lt;br /&gt;
Wichtig sind auf jeden Fall [[#Die 6 Zustände]]. Der Mikrocontroller muss die Phasen jeweils nacheinander so wie in der Tabelle ansteuern. Das ist soweit ja kein Problem, schwierig ist aber immer der richtige Zeitpunkt für die Kommutierung zu finden.&lt;br /&gt;
&lt;br /&gt;
Falls man einen IR2104 oder einen ähnlichen Treiber verwendet, würde die Software ungefähr so aussehen:&lt;br /&gt;
&lt;br /&gt;
* Beim Programmstart wird schonmal der PWM-Ausgang mit einem Timer aktiviert. Die Frequenz liegt normalerweise so im Bereich 12 bis 25kHz. Ich selber verwende 20kHz, da hört man dann auch dieses Pfeifen nicht mehr.&lt;br /&gt;
* Der Interrupt vom Analogkomparator muss aktiviert werden, um die Kommutierungszeitpunkte bestimmen zu können.&lt;br /&gt;
* Dann habe ich eine Funktion, welche den Zustand (1 bis 6) eins weiterschaltet und die Ausgänge entsprechend setzt. Dabei werden die Pins, die das PWM-Signal enthalten sollen, einfach als Eingang definiert, wie ich schonmal erwähnte.&lt;br /&gt;
* Wichtig ist ausserdem, dass bei jeder Kommutierung auch noch der richtige ADC-Kanal auf den Komparator geleitet wird per Multiplexer. Dieser Kanal wird bei jeder Kommutierung eins weitergeschaltet.&lt;br /&gt;
* Danach muss nur noch gewartet werden bis der Analogkomparator einen Interrupt auslöst. Sobald dies geschieht, wird die nächste Kommutierung per Timer (30° Verzögerung) ausgelöst, und das Spiel beginnt wieder von vorne.&lt;br /&gt;
&lt;br /&gt;
Je nach Komplexität des BLDC Controllers und des damit verbundenen Programmieraufwands ist es aber auch möglich (wie von sehr vielen Nutzern implementiert) die Kommutierung direkt nach dem Analog-Komparator Interrupt auszulösen - d.h. mit 0° Verzögerung. In diesem Fall spricht man von Phasenvoreilender (phaseadvance) Ansteuerung. Der Motor kann dadurch eine höhere Maximaldrehzahl erreichen, jedoch mit geringerem Drehmoment - die Stromaufnahme ist höher und der Wirkungsgrad geringer (siehe [http://ww1.microchip.com/downloads/en/AppNotes/01083a.pdf AN1083, Seite 18]). Der Effekt ist ähnlich dem Feldschwächebetrieb einer Asynchronmaschine.&lt;br /&gt;
&lt;br /&gt;
Die Drehzahl des Motors lässt sich jetzt ganz bequem ändern, indem man den Duty-Cycle des PWM-Signales verändert. Der Motor beschleunigt bzw. bremst dann von alleine. Übrigens ist es empfehlenswert, den Sollwert etwas zu &amp;quot;dämpfen&amp;quot;, damit keine schlagartigen Änderungen des Duty-Cycles erfolgen können. Vor allem schlagartige Abbremsmanöver können starke Überspannungsspitzen hervorrufen, die den Regler zerstören können!&lt;br /&gt;
&lt;br /&gt;
=== Anlauf ===&lt;br /&gt;
&lt;br /&gt;
So, das war jetzt die Beschreibung für einen Motor, der bereits läuft. &#039;&#039;&#039;Bis&#039;&#039;&#039; der Motor allerdings mal dreht, muss man anders vorgehen, weil der stillstehende Motor ja keine Komparator-Interrupts auslöst, da keine BEMF vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Daher muss man den Motor zuerst mit einem starren Drehfeld auf eine gewisse Drehzahl beschleunigen, wie bei einem Schrittmotor. Sobald eine genügend hohe Drehzahl erreicht wurde, kann man in den geregelten Betrieb schalten. Am besten schaltet man dazu einfach alle Phasen ab und aktiviert den Komparator. Sobald der erste Interrupt vom Komparator ausgelöst wird, werden die Phasen wieder eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
Der ganze Startvorgang ist aber schon eine Wissenschaft für sich. Es braucht (nach meiner Erfahrung) viel Zeit und Nerven, bis alles richtig funktioniert. Man kann aber am Anfang den Motor auch von Hand anwerfen, das geht viel einfacher als mit einer Zwangskommutierung. Ein Oszilloskop ist eigentlich auch absolut notwendig, um analysieren zu können was der Regler und die BEMF genau macht. &lt;br /&gt;
&lt;br /&gt;
Ganz wichtig aber an dieser Stelle: &#039;&#039;&#039;Wenn der Motor mit einem starren Drehfeld angesteuert wird, sieht die BEMF alles andere als schön aus!&#039;&#039;&#039; Das liegt daran, dass der Motor bei jeder Kommutierung beschleunigt, und danach wieder abgebremst wird, der Motor läuft einfach nicht „rund“. Wenn ihr also irgendwas komisches auf dem Oszilloskop seht, ist das kein Fehler in eurer Schaltung, das ist normal bei Zwangskommutierung!&lt;br /&gt;
&lt;br /&gt;
Wenn Ihr die BEMF auf dem Oszilloskop anschauen wollt, könnt Ihr entweder den Motor einfach von Hand drehen, oder ihr dreht den Motor mit Zwangskommutierung hoch, und schaltet dann alle Phasen ab (nicht auf GND, in der Luft hängend). Direkt nach dem Abschalten der Phasen sollte die BEMF einen relativ schönen Drehstrom zeigen (muss ich selbst noch kontrollieren ob das wirklich der Fall ist :-) )&lt;br /&gt;
Anmerkung JB: Gerade an einem Festplattenmotor getestet, bei Drehung von der Hand lassen bis zu 600mVss sinusförmig auf dem Oszilloskop blicken, Frequenz bis zu 20 Hz, muss sich umeinen mehrpoligen Motor Handeln, so schnell hab ich nicht gedreht ;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bis jetzt habe ich es mit dieser Variante aber noch nicht so richtig geschafft, einen brauchbaren Anlaufvorgang hinzukriegen. Ich glaube auch, dass gekaufte Regler das nicht so machen. Diese scheinen nur einen kräftigen Strom auf eine Phase zu geben, und werten dann die entstandene BEMF aus, aus der dann berechnet werden kann, welche Phase als nächstes bestromt werden muss. So richtig habe ich das aber noch nicht angeschaut, &#039;&#039;&#039;vielleicht weiss hier jemand besser Bescheid und könnte es hier beschreiben?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Prinzip eines Anlaufvorgangs eines sensorlosen BLDC ist folgendes:&lt;br /&gt;
- Man präge ein Feld ein, bei dem angenommen werden muss, dass der Motor diesem ab Stillstand auch folgt.&lt;br /&gt;
- Sobald diese Annahme durch Auftreten eines durch BEMF erzeugten Ereignisses bestätigt wird, kann in den geregelten Betrieb umgeschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Es ist mitunter Hilfreich zum Starten eine Delay-Tabelle zu verwenden, damit braucht man sich nicht durch eine feste Frequenz-Vorgabe selbst zu bremsen. Dauert evtl. etwas beim Einstellen,&lt;br /&gt;
soll aber laut Atmel-Application-Note für BLCD-Motoren funktionieren. Den Rotor vorher noch durch Bestromen einer Phase und danach warten in eine definierte Anfangsposition drehen.&lt;br /&gt;
&lt;br /&gt;
=== Komparator ===&lt;br /&gt;
&lt;br /&gt;
Wenn man sich für die Kommutierungs-Erkennung per Analogkomparator entscheidet, muss man noch ein sehr nützliches Feature von den AVRs kennen. Da man ja abwechslungsweise drei verschiedene Signale (BEMF_A...C) mit der Mittelpunktspannung vergleichen muss, aber nur ein einziger Analogkomparator vorhanden ist, muss man den sogenannten Analog-Multiplexer benutzen. Mit diesem in den AVRs integrierten Multiplexer kann man nun die Spannung am Pin &amp;quot;AIN0&amp;quot; mit einem beliebigen Analogeingang (ADC0...ADC7) vergleichen. Natürlich kann man nicht mehrere Kanäle gleichzeitig anwählen, da es nur einen einzigen Komparator gibt. Das ist für unsere Anwendung allerdings kein Problem, wir müssen immer nur eines der BEMF-Signale mit der Mittelpunktspannung vergleichen.&lt;br /&gt;
&lt;br /&gt;
Näheres dazu und wie man den Multiplexer benutzt erfährt man im Datenblatt des verwendeten Mikrocontrollers. Der entsprechende Abschnitt heisst &amp;quot;Analog Comparator Multiplexed Input&amp;quot; (unter &amp;quot;Analog Comparator&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== Schnittstellen ===&lt;br /&gt;
&lt;br /&gt;
Man kann nun den Sollwert der Drehzahl wahlweise über einen PPM-Eingang, über [[UART]], [[SPI]], [[I2C]] oder mit einem Potentiometer vorgeben. Welche Ansteuerung man wählt hängt davon ab, wie und wo der Motor eingesetzt werden soll und ist deshalb jedem selber überlassen.&lt;br /&gt;
&lt;br /&gt;
== Bildmaterial ==&lt;br /&gt;
=== Oszillogramme ===&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Phasen_PWM.png|300px]]&lt;br /&gt;
&lt;br /&gt;
Die drei Phasen während dem geregelten Betrieb, die BEMF ist sehr schön zu erkennen (immer zwischen den Zuständen &amp;quot;PWM&amp;quot; und &amp;quot;LOW&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Phasen_Vollgas.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So sehen die drei Phasen bei Vollgas aus (100% PWM). Die BEMF ist jetzt sogar so steil, dass sie die beiden Zustände &#039;&#039;Low&#039;&#039; und &#039;&#039;High&#039;&#039; mit einer fast perfekten Geraden verbindet!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_BEMF_richtig.png|300px]]&lt;br /&gt;
&lt;br /&gt;
* Gelb: Phase A, BEMF sehr schön erkennbar&lt;br /&gt;
* Blau: Mittelpunktspannung&lt;br /&gt;
* Rot: BEMF von Phase A (nach der BEMF-Schaltung!)&lt;br /&gt;
* Grün: Komparator-Interrupts (steigende Flanke) Jeder dritte Interrupt gehört zur Phase A, die anderen Interrupts stammen von den anderen Phasen, die nicht auf dem Bild zu sehen sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_BEMF_falsch.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So kann z.B. die BEMF während der Zwangskommutierung aussehen. Dadurch werden auch zu viele Komparator-Interrupts (Grün, jede Flanke) ausgelöst. Kein schöner Anblick...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Anlauf_1.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So sieht der Anlaufvorgang bei einem gekauften Regler aus. eine extrem kurze Geschichte im Vergleich mit meinen paar Umdrehungen mit Zwangskommutierung. Wer kennt das Geheimnis? &lt;br /&gt;
Sieht so aus als würde für eine kurze Zeit Strom eingeprägt um den Motor in eine definierte, stehende Position zu bringen. Danach wird weiter kummutiert, der Motor dreht an und es wird sofort ueber die BEMF kommutiert.&lt;br /&gt;
&lt;br /&gt;
=== Layouts ===&lt;br /&gt;
&lt;br /&gt;
Als Anregung, wie so ein Regler aussehen könnte (nur 40x26mm klein, inklusive Optokoppler, drei Treibern und drei schönen Stecker!):&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Eagle3d_top_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Eagle3d_bot_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
Der HCPL-0600 auf der Unterseite ist übrigens ein Optokoppler um das PPM-Eingangssignal galvanisch zu entkoppeln. Ist nicht zwingend nötig, war aber grad Platz da... :-)&lt;br /&gt;
&lt;br /&gt;
== Siehe Auch ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/248509 Diskussion zum Artikel]&lt;br /&gt;
* [[BLDC Demo Board]]&lt;br /&gt;
* [[Treiber]]&lt;br /&gt;
* [[Mosfet-Übersicht]]&lt;br /&gt;
* [[Leiterbahnbreite]] Unbedingt beachten bei grösseren Strömen!&lt;br /&gt;
* [[Kühlkörper]] Bei sehr hohen Strömen evtl. nötig&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.atmel.com/Images/doc8012.pdf AppNote AVR444 von Atmel]&lt;br /&gt;
* [http://ww1.microchip.com/downloads/en/AppNotes/00885a.pdf BLDC Theorie(AN885 Microchip)]&lt;br /&gt;
* [http://www.mikrokopter.de/ucwiki/BrushlessCtrl BrushlessCtrl vom Mikrokopter]&lt;br /&gt;
* [http://svn.mikrokopter.de/listing.php?repname=BL-Ctrl&amp;amp; Software vom Mikrokopter Brushless-Regler]&lt;br /&gt;
* [http://home.versanet.de/~b-konze/ Die Seite von B. Konze, einer der Pioniere in diesem Bereich]&lt;br /&gt;
* [http://www.rcgroups.com/forums/showthread.php?t=1513678 Ein Thema auf rcgroups.com (Englisch) wo einige käuflichen Regler näher angeschaut wurden und eine eigene Firmware angeboten wird]&lt;br /&gt;
* [http://rmmx.gmxhome.de/bldchv/start.html Ein Regler-Projekt für etwas grössere Motoren]&lt;br /&gt;
* [http://www.fc00.de/quadrokopter_6_kw.htm Regler für sehr grosse Motoren]&lt;br /&gt;
* [http://ww1.microchip.com/downloads/en/AppNotes/01083a.pdf Appnote AN1083 von Microchip, sehr detailliert]&lt;br /&gt;
[[Kategorie:Motoren]]&lt;/div&gt;</summary>
		<author><name>46.128.38.250</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Brushless-Controller_f%C3%BCr_Modellbaumotoren&amp;diff=66429</id>
		<title>Brushless-Controller für Modellbaumotoren</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Brushless-Controller_f%C3%BCr_Modellbaumotoren&amp;diff=66429"/>
		<updated>2012-05-19T12:02:40Z</updated>

		<summary type="html">&lt;p&gt;46.128.38.250: /* Anlauf */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Im Internet gibt es einige grundlegende Informationen zur Funktionsweise und Ansteuerung von Brushless-Motoren (BLDC). Für die Entwicklung eines solchen Reglers findet man aber nur wenig richtig detaillierte Informationen und Erfahrungsberichte. In diesem Artikel sollen genau diese Lücken geschlossen werden. Es soll hier aber kein fertiges Produkt (Schaltplan + Layout + Software) angeboten werden. Viel mehr soll es die Eigenentwicklung unterstützen, Ideen und Erfahrungen anbieten.&lt;br /&gt;
&lt;br /&gt;
An dieser Stelle weise ich noch darauf hin, dass man bei den [[#Weblinks]] noch einige sehr gute Informationen findet! Es gibt dort Hardware und Software, es lohnt sich die Links mal anzuschauen.&lt;br /&gt;
&lt;br /&gt;
==== Um welche Motoren geht es genau? ====&lt;br /&gt;
&lt;br /&gt;
Es geht hier um die sogenannten elektrisch kommutierten bürstenlosen Gleichstrommotoren (BLDC) aus dem Modellbaubereich. &lt;br /&gt;
&lt;br /&gt;
Deren Eigenschaften sind:&lt;br /&gt;
* Haben drei Anschlüsse für die drei Phasen, ansonsten sind keine weiteren Anschlüsse vorhanden&lt;br /&gt;
* Werden in der Regel mit LiPo Akkus versorgt&lt;br /&gt;
* Leistung im Bereich von ca. 100W bis 2kW&lt;br /&gt;
* Spannungen im Bereich von ca. 10 bis 50V&lt;br /&gt;
* Ströme im Bereich von ca. 5 bis 120A&lt;br /&gt;
&lt;br /&gt;
==== Um welche Motoren geht es hier nicht? ====&lt;br /&gt;
&lt;br /&gt;
* Motoren mit Hallsensoren für die Rückmeldung&lt;br /&gt;
* Festplattenmotoren&lt;br /&gt;
&lt;br /&gt;
Unter Umständen kann aber dieser Artikel auch für solche Motoren nützlich sein.&lt;br /&gt;
&lt;br /&gt;
== Funktionsweise dieser Motoren ==&lt;br /&gt;
&lt;br /&gt;
=== Ansteuerung ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:BLDC_Spannungs_Diagramm.png|thumb|right|250px|Ansteuerung der 3 Phasen]]&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich werden die 3 Phasen nacheinander bestromt, die Phasenspannungen wären also drei um 120° phasenverschobene Rechteckspannungen. Ein sinusförmiger Drehstrom ist nicht nötig, es genügen Rechteckspannungen. Mit einer Raumzeigermodulation könnte man die Stromaufnahme und die Geräuschentwicklung zwar noch verringern, macht die Ansteuerung aber einiges aufwändiger. Sogar die käuflichen Regler arbeiten nur mit Rechtecksignalen, zumindest die die ich kenne. &lt;br /&gt;
&lt;br /&gt;
Dabei gibt es für jede Phase die Zustände „Low“, „High“ und „Floating“. Low bedeutet 0V (GND), High entspricht der Versorgungsspannung und Floating ist keines von beidem, die Phase „hängt in der Luft“. Bei „High“ wird aber noch der Mittelwert der Spannung per PWM eingestellt, über das Tastverhältnis wird schlussendlich die Drehzahl verändert! Dazu aber später mehr.&lt;br /&gt;
&lt;br /&gt;
In der Grafik rechts kann man den Spannungsverlauf sehr gut erkennen. Das Diagramm zeigt aber nur den theoretischen Verlauf der Spannungen, wobei die gestrichelten Linien den Zustand &amp;quot;floating&amp;quot; symbolisieren. Dies kann man in einem Diagramm ja nicht wirklich darstellen, das ist einfach symbolisch gemeint. Interessanterweise sehen die Spannungen aufgrund der BEMF aber tatsächlich ziemlich ähnlich aus wie im Diagramm!&lt;br /&gt;
&lt;br /&gt;
=== Die 6 Zustände ===&lt;br /&gt;
&lt;br /&gt;
Wie man erkennen kann, werden 6 Zustände gebraucht, die sich dann immer wiederholen. Die Kommutierung ist also einfach ein Weiterschalten des Zustandes. &lt;br /&gt;
&#039;&#039;Diese 6 Zustände sind nicht mit den drei Zuständen von oben (High, Low, Floating) zu verwechseln, das ist ein anderes Thema!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In einer Tabelle dargestellt würde das folgendermassen aussehen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Zustand || Phase A || Phase B || Phase C || Stromfluss || Komparator-Eingänge&lt;br /&gt;
|-&lt;br /&gt;
| 1 || PWM || Floating || GND || A --&amp;gt; C || MITTEL &amp;lt;--&amp;gt; NULL_B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Floating || PWM || GND || B --&amp;gt; C || MITTEL &amp;lt;--&amp;gt; NULL_A&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GND || PWM || Floating || B --&amp;gt; A || MITTEL &amp;lt;--&amp;gt; NULL_C&lt;br /&gt;
|-&lt;br /&gt;
| 4 || GND || Floating || PWM || C --&amp;gt; A || MITTEL &amp;lt;--&amp;gt; NULL_B&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Floating || GND || PWM || C --&amp;gt; B || MITTEL &amp;lt;--&amp;gt; NULL_A&lt;br /&gt;
|-&lt;br /&gt;
| 6 || PWM || GND || Floating || A --&amp;gt; B || MITTEL &amp;lt;--&amp;gt; NULL_C&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Hinweise:&lt;br /&gt;
* Die Nummern in der ersten Spalte entsprechen genau den sechs Zuständen, die auch im obigen Diagramm nummeriert sind (Alle 6 Zustände zusammen bilden einen Zyklus, wie es auch im Diagramm dargestellt ist)&lt;br /&gt;
* Den Inhalt der letzten Spalte wird später noch erläutert. Die Bezeichnungen beziehen sich auf die [[#BEMF-Schaltung]].&lt;br /&gt;
&lt;br /&gt;
=== Einsatz der BEMF ===&lt;br /&gt;
Das schaut bis jetzt eigentlich wie ein Synchronmotor oder Schrittmotor aus, was ein BLDC im Prinzip auch ist.  &lt;br /&gt;
&lt;br /&gt;
Wie schon erwähnt wurde, wird ein BLDC elektronisch kommutiert. Das heisst, die Kommutierung wird nicht einfach stur vorgegeben, sondern es wird immer Rücksicht auf die Ankerposition genommen. Dazu muss man allerdings wissen, wann man die Kommutierung genau auslösen soll. &lt;br /&gt;
&lt;br /&gt;
Dieses Verfahren heißt Block-Kommutierung und ist ein Kompromiss aus Aufwand und Ergebnis:&lt;br /&gt;
Idealerweise werden die Ströme im Stator so eingeprägt, dass der Statorfluss dem Rotorfluss immer um 90° vorauseilt. Nur so wir das ideale Drehmoment erzeugt (siehe Literatur zur permanenterregten Synchronmaschine). Allerdings hat dieses Verfahren, auch Feldorientierte Regelung oder Vektor-Regelung genannt, den Nachteil, dass meistens teure Positionssensorik für den Rotor nowendig ist und auch die nötige Rechenleistung stark ansteigt. Die komplette Regelung muss für jede PWM-Periode gerechnet werden, damit sich der Aufwand lohnt. &lt;br /&gt;
Im Fall der Block-Kommutierung ist der ideale Kommutierungszeitpunkt also der, bei dem das Stator-Feld dem Rotor-Feld im Mittel um 90 ° vorauseilt. Dieser ideale Kommutierungszeitpunkt ist wegen der als konstant angenommenen Rechenzeit für die Kommutierung drehzahlabhängig.&lt;br /&gt;
&lt;br /&gt;
Zur Erreichung einer höheren Maximaldrehzahl kann das Rotorfeld durch das Statorfeld im sogenannten Feldschwäch-Betrieb geschwächt werden. Es ergeben sich Feldschwäch-(Blind)ströme im Bereich der Nennströme.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich kann auch ein BLDC nicht ohne Kenntnis der Lage des Rotors kommutiert werden. Und hier kommt die sogenannte Back Electromotive Force (BEMF) zum Einsatz. Von den drei Phasen liegt ja zu jedem Zeitpunkt genau eine Phase in der Luft wie man am Diagramm oben erkennen kann. Aufgrund des drehenden Magnetfeldes im Motor wird an dieser Phase nun eine Spannung induziert. Und genau diese induzierte Spannung gibt nun Auskunft darüber, in welchem Winkel sich der Anker befindet, und daraus kann man dann auch den Zeitpunkt der nächsten Kommutierung bestimmen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich wird aber auch noch die Sternmittelpunktspannung der drei Phasen benötigt, welche aber leider nicht direkt zur Verfügung steht. Das ist aber kein Problem, mit drei Widerständen kann man sich die selber erzeugen (siehe [[#BEMF-Schaltung]]).&lt;br /&gt;
&lt;br /&gt;
Jetzt sollten die BEMF-Spannungen die Sternmittelpunktspannung ständig kreuzen, was man dann mit einem Komparator erfassen kann. Und den Interrupt, den der Komparator auslöst, ist nun verantwortlich für die nächste Kommutierung.&lt;br /&gt;
Der Komparator wird natürlich nacheinander mit den drei Phasen gefüttert, es darf immer nur die Phase an den Komparator angeschlossen sein, die auch in der Luft hängt! In der Tabelle [[#Die 6 Zustände]] sieht man, welche zwei Spannungen der Komparator jeweils vergleichen muss.&lt;br /&gt;
&lt;br /&gt;
Als Komparator kann man übrigens den integrierten nehmen, den es in den AVRs gibt. Diese (alle?) haben auch den benötigten Multiplexer, um zwischen den drei Analogquellen wählen zu können. Näheres dazu im Abschnitt [[#Software]].&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Leistungsteil ===&lt;br /&gt;
&lt;br /&gt;
==== Treiber ====&lt;br /&gt;
&lt;br /&gt;
Um die drei notwendigen Zustände (&#039;&#039;Low&#039;&#039;, &#039;&#039;High&#039;&#039; und &#039;&#039;Floating&#039;&#039;) für jede der drei Phasen realisieren zu können, werden drei Halbbrücken mit Mosfets benötigt. Hier gibt es dann auch schon mehrere Varianten, wie man das aufbauen kann. Grundsätzlich muss man sich mal überlegen ob fertige FET-Treiber oder diskrete Treiber verwendet werden sollen. Die FET-Treiber haben einige sehr schöne Vorteile, deshalb sollte man diese meiner Meinung nach bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Die Vorteile wären:&lt;br /&gt;
&lt;br /&gt;
* Integrierter Kurzschlussschutz mit dead time, ein Softwarefehler kann die FETs nicht zerstören. Das kann in der Entwicklungsphase sehr von Vorteil sein :-)&lt;br /&gt;
* Die FETs können mit ordentlicher Geschwindigkeit geschaltet werden, und die Mikrocontroller-Ports werden trotzdem nicht stark belastet. So kann die Wärmeentwicklung der FETs noch etwas reduziert werden.&lt;br /&gt;
* Bei Treibern die mit nur einem Eingang zwischen Lowside und Highside Mosfets toggeln (z.B. IR2104), ist der sogenannte „aktiver Freilauf“ bereits in Hardware realisiert und ermöglicht so mit wenig Aufwand eine extrem niedrige Erwärmung der Mosfets. Das ermöglicht schon sehr grosse Ströme auch ohne Kühlkörper!&lt;br /&gt;
* Es können günstigere Mosfets verwendet werden, es müssen keine TTL-Kompatible FETs sein. Auch ist eine niedrige Gatekapazität nicht so von Bedeutung wie bei direkter Ansteuerung mit einem Mikrocontroller.&lt;br /&gt;
* Je nach dem welchen Treiber man verwendet, kann der Softwareaufwand und die Fehleranfälligkeit deutlich reduziert werden.&lt;br /&gt;
&lt;br /&gt;
Nachteile von Treiber sind:&lt;br /&gt;
&lt;br /&gt;
* Mehr Bauteile auf der Platine.&lt;br /&gt;
* Vermutlich insgesamt etwas teurer, auch wenn die FETs günstiger sind.&lt;br /&gt;
* Bei vielen Treibern ist eine Minimalspannung von ca. 10V notwendig, damit sie funktionieren. Bei einem fast leeren 3S LiPo Akku könnte das vielleicht schon kritisch werden. Auch darf z.B. beim IR2104 eine Spannung von 20V nicht überschritten werden. Daher kommt (ohne StepUp und StepDown Wandler) eigentlich fast nur noch ein 4S Akku in Frage. Möchte man einen grösseren Eingangsspannungsbereich haben muss man noch entsprechende Spannungsregler einbauen.&lt;br /&gt;
&lt;br /&gt;
Ich persönlich habe es schon mit einem IR2104S probiert, dieser erscheint mir sehr geeignet für diese Aufgabe. Ich betreibe ihn mit einem 4S LiPo, damit läuft das Teil perfekt. Kann ich nur weiterempfehlen!&lt;br /&gt;
&lt;br /&gt;
==== Beispielschaltung ====&lt;br /&gt;
[[Datei:BLDC_Leistungsteil_1.png|thumb|right|300px|Beispiel einer Halbbrücke inklusive Strommessung]]&lt;br /&gt;
Hier ein Beispiel, wie der Leistungsteil einer Phase aussehen könnte.&lt;br /&gt;
&lt;br /&gt;
Für die exakte Beschaltung der Treiber muss man natürlich dessen Datenblatt studieren!&lt;br /&gt;
&lt;br /&gt;
Hier sieht man auch gleich noch die Strommessung, die man natürlich nicht für jede Phase einzeln aufbauen muss. Man kann sie sogar ganz weglassen, sie könnte aber nützlich sein um eine Überlast des Motores erkennen zu können.&lt;br /&gt;
&lt;br /&gt;
Der Widerstand R20 ist dazu da, dass auf dem Treiber das PWM-Signal liegt, sobald die Leitung „IN_A“ in der Luft hängt (uC Pin als Eingang definiert). So wird nur ein einziger PWM-Ausgang vom Mikrocontroller benötigt für alle drei Phasen, erfordert also kein Soft-PWM oder sonst irgend ein Murks. Diese Schaltung habe ich übrigens beim Mikrokopter-Projekt abgeschaut.&lt;br /&gt;
&lt;br /&gt;
Übrigens muss an die Versorgung unbedingt noch ein grosser Elko gehängt werden, am besten möglichst nahe an die Mosfets (keine langen Leitungen zwischen Elko und Mosfets). Die erforderliche Kapazität hängt davon ab, wieviel Strom der Motor braucht. bei kleinen bis mittleren Motoren sollten so 220uF bis 680uF ausreichend sein.&lt;br /&gt;
&lt;br /&gt;
=== BEMF-Schaltung ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:BLDC_BEMF_schaltung.png|thumb|right|300px|BEMF-Schaltung]]&lt;br /&gt;
&lt;br /&gt;
Ein wichtiger Teil ist aber auch die BEMF-Schaltung. Dabei wird häufig die Schaltung vom Mikrokopter eingesetzt (siehe Schaltung rechts).&lt;br /&gt;
&lt;br /&gt;
Die Schaltung besteht erstmal aus drei Spannungsteilern, die die Phasenspannungen auf ein Spannungsniveau heruntersetzen, das man auf die Mikrokontrollereingänge legen darf. Keramikkondensatoren glätten diese Spannungen, weil die aufgrund der PWM sonst sehr stark ausschlagen. Dann gehen diese drei Spannungen (&#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039;) auf drei ADC-Eingänge des Mikrocontrollers.&lt;br /&gt;
&lt;br /&gt;
Und dann sind da noch die drei Widerstände, die aus den Spannungen &#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039; einen virtuellen Sternmittelpunkt bilden. Diese Mittelpunktspannung (&#039;&#039;MITTEL&#039;&#039;) kommt dann auf den Komparatoreingang &#039;&#039;AIN0&#039;&#039; vom AVR. Diese Spannung soll der Komparator später dann mit jeweils einer der Spannungen &#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039; vergleichen um den Kommutierungszeitpunkt bestimmen zu können.&lt;br /&gt;
&lt;br /&gt;
Man kann die Widerstands-/ und Kapazitätswerte auch noch anpassen. Bei höheren Eingangsspannungen muss man darauf achten, dass die Eingänge vom AVR keine zu hohe Spannung abkriegen! Ein Regler, den ich gekauft habe, hat einiges höhere Widerstandswerte und kommt sogar ohne Kondensatoren aus. Hier hat man also durchaus noch Spielraum um ein bisschen zu tüfteln, für den Anfang ist die abgebildete Schaltung aber bestens geeignet.&lt;br /&gt;
&lt;br /&gt;
=== Mikrocontroller ===&lt;br /&gt;
&lt;br /&gt;
Als Mikrocontroller sind viele Typen aus der AVR-Serie geeignet. Bei der BrushlessCtrl wird zum Beispiel ein ATMega168 eingesetzt. Mit diesem habe ich auch mal angefangen, der scheint wirklich gut geeignet zu sein. Es reicht aber auch ein ATMega88 wenn man nicht alle möglichen Protokolle und Ansteuerungsarten (I2C, SPI, PPM) gleichzeitig einbauen will.&lt;br /&gt;
&lt;br /&gt;
Viele Regler verwenden auch einen AT90PWM, vorallem wenn mehrere PWM-Kanäle gebraucht werden.&lt;br /&gt;
&lt;br /&gt;
Übrigens wird bei käuflichen Reglern extrem häufig ein ATMega8 eingesetzt! Wenn man nur Software entwickeln möchte kann man auch einen solchen Regler kaufen und das eigene Programm aufspielen. Bei den [[#Weblinks]] findet man dazu auch noch Informationen.&lt;br /&gt;
&lt;br /&gt;
Um eine Raumzeigermodulation zu implementieren wird dann aber vermutlich schon ein 32-Bit Mikrocontroller nötig sein. Aber wie schon erwähnt ist für ein Modellbaumotor eine Raumzeigermodulation keinesfalls ein must-have.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Bei der Software kommt es jetzt natürlich sehr stark darauf an, wie die Hardware aufgebaut ist. Ich möchte hier aber nicht auf jede Variante eingehen, das gäbe viel zu viel Arbeit. Auch will ich ja kein fertiger Code bereitstellen, sondern nur Hinweise und Tipps geben. Wer nicht selber programmieren will, der kann ja mal die Mikrokopter-Firmware herunterladen, die älteren Versionen davon gibt es auf der Mikrokopter-Seite zum downloaden.&lt;br /&gt;
&lt;br /&gt;
Wichtig sind auf jeden Fall [[#Die 6 Zustände]]. Der Mikrocontroller muss die Phasen jeweils nacheinander so wie in der Tabelle ansteuern. Das ist soweit ja kein Problem, schwierig ist aber immer der richtige Zeitpunkt für die Kommutierung zu finden.&lt;br /&gt;
&lt;br /&gt;
Falls man einen IR2104 oder einen ähnlichen Treiber verwendet, würde die Software ungefähr so aussehen:&lt;br /&gt;
&lt;br /&gt;
* Beim Programmstart wird schonmal der PWM-Ausgang mit einem Timer aktiviert. Die Frequenz liegt normalerweise so im Bereich 12 bis 25kHz. Ich selber verwende 20kHz, da hört man dann auch dieses Pfeifen nicht mehr.&lt;br /&gt;
* Der Interrupt vom Analogkomparator muss aktiviert werden, um die Kommutierungszeitpunkte bestimmen zu können.&lt;br /&gt;
* Dann habe ich eine Funktion, welche den Zustand (1 bis 6) eins weiterschaltet und die Ausgänge entsprechend setzt. Dabei werden die Pins, die das PWM-Signal enthalten sollen, einfach als Eingang definiert, wie ich schonmal erwähnte.&lt;br /&gt;
* Wichtig ist ausserdem, dass bei jeder Kommutierung auch noch der richtige ADC-Kanal auf den Komparator geleitet wird per Multiplexer. Dieser Kanal wird bei jeder Kommutierung eins weitergeschaltet.&lt;br /&gt;
* Danach muss nur noch gewartet werden bis der Analogkomparator einen Interrupt auslöst. Sobald dies geschieht, wird die nächste Kommutierung ausgelöst, und das Spiel beginnt wieder von vorne.&lt;br /&gt;
&lt;br /&gt;
Ich glaube aber, dass dies noch nicht die ganz richtige Art ist, wie man die Kommutierung auslöst. Ich denke, man müsste nach einem Interrupt eine gewisse Zeit warten (je nach Kommutierungswinkel oder wie das heisst) und erst kurz vor dem nächsten Interrupt die Kommutierung auslösen. Also quasi immer einen Zustand später. Dazu muss aber die Verzögerungszeit ständig ausgerechnet werden, damit die auch bei jeder Drehzahl stimmt. Ich habe es selber noch nicht so implementiert, kann daher nicht sagen ob das so dann richtig funktioniert. &#039;&#039;&#039;Falls hier jemand besser Bescheid weiss, wäre es cool wenn man das hier noch ergänzen könnte.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Laut Literatur liegt der optimale Kommutierungszeitpunkt 30° nach dem Nulldurchgang der Spannung am nicht beschalteten Eingang. Die naheliegendste Möglichkeit wäre also die Zeit, die bei der aktuellen Drehzahl für eine Umdrehung benötigt wird, durch zwölf zu dividieren und so lange bis zur Kommutierung zu warten.&lt;br /&gt;
&lt;br /&gt;
Ausserdem scheint es auch Regler zu geben, die eine Kommutierung nicht mit dem Analogkomparator erfassen, sondern direkt mit ADC-Wandlungen. Dazu weiss ich aber leider auch nichts näheres, deshalb auch hier: &#039;&#039;&#039;Wenn jemand weiss, was es damit auf sich hat, bitte melden.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Drehzahl des Motores lässt sich jetzt ganz bequem ändern, indem man den Duty-Cycle des PWM-Signales verändert. Der Motor beschleunigt bzw. bremst dann von alleine.&lt;br /&gt;
&lt;br /&gt;
=== Anlauf ===&lt;br /&gt;
&lt;br /&gt;
So, das war jetzt die Beschreibung für einen Motor, der bereits läuft. &#039;&#039;&#039;Bis&#039;&#039;&#039; der Motor allerdings mal dreht, muss man anders vorgehen, weil der stillstehende Motor ja keine Komparator-Interrupts auslöst, da keine BEMF vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Daher muss man den Motor zuerst mit einem starren Drehfeld auf eine gewisse Drehzahl beschleunigen, wie bei einem Schrittmotor. Sobald eine genügend hohe Drehzahl erreicht wurde, kann man in den geregelten Betrieb schalten. Am besten schaltet man dazu einfach alle Phasen ab und aktiviert den Komparator. Sobald der erste Interrupt vom Komparator ausgelöst wird, werden die Phasen wieder eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
Der ganze Startvorgang ist aber schon eine Wissenschaft für sich. Es braucht (nach meiner Erfahrung) viel Zeit und Nerven, bis alles richtig funktioniert. Man kann aber am Anfang den Motor auch von Hand anwerfen, das geht viel einfacher als mit einer Zwangskommutierung. Ein Oszilloskop ist eigentlich auch absolut notwendig, um analysieren zu können was der Regler und die BEMF genau macht. &lt;br /&gt;
&lt;br /&gt;
Ganz wichtig aber an dieser Stelle: &#039;&#039;&#039;Wenn der Motor mit einem starren Drehfeld angesteuert wird, sieht die BEMF alles andere als schön aus!&#039;&#039;&#039; Das liegt daran, dass der Motor bei jeder Kommutierung beschleunigt, und danach wieder abgebremst wird, der Motor läuft einfach nicht „rund“. Wenn ihr also irgendwas komisches auf dem Oszilloskop seht, ist das kein Fehler in eurer Schaltung, das ist normal bei Zwangskommutierung!&lt;br /&gt;
&lt;br /&gt;
Wenn Ihr die BEMF auf dem Oszilloskop anschauen wollt, könnt Ihr entweder den Motor einfach von Hand drehen, oder ihr dreht den Motor mit Zwangskommutierung hoch, und schaltet dann alle Phasen ab (nicht auf GND, in der Luft hängend). Direkt nach dem Abschalten der Phasen sollte die BEMF einen relativ schönen Drehstrom zeigen (muss ich selbst noch kontrollieren ob das wirklich der Fall ist :-) )&lt;br /&gt;
&lt;br /&gt;
Bis jetzt habe ich es mit dieser Variante aber noch nicht so richtig geschafft, einen brauchbaren Anlaufvorgang hinzukriegen. Ich glaube auch, dass gekaufte Regler das nicht so machen. Diese scheinen nur einen kräftigen Strom auf eine Phase zu geben, und werten dann die entstandene BEMF aus, aus der dann berechnet werden kann, welche Phase als nächstes bestromt werden muss. So richtig habe ich das aber noch nicht angeschaut, &#039;&#039;&#039;vielleicht weiss hier jemand besser Bescheid und könnte es hier beschreiben?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Prinzip eines Anlaufvorgangs eines sensorlosen BLDC ist folgendes:&lt;br /&gt;
- Man präge ein Feld ein, bei dem angenommen werden muss, dass der Motor diesem ab Stillstand auch folgt.&lt;br /&gt;
- Sobald diese Annahme durch Auftreten eines durch BEMF erzeugten Ereignisses bestätigt wird, kann in den geregelten Betrieb umgeschaltet werden.&lt;br /&gt;
&lt;br /&gt;
=== Schnittstellen ===&lt;br /&gt;
&lt;br /&gt;
Man kann nun den Sollwert der Drehzahl wahlweise über einen PPM-Eingang, über UART, SPI oder I2C vorgeben. Das überlasse ich aber jedem selber, es kommt natürlich darauf an wo der Regler schlussendlich eingesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
== Bildmaterial ==&lt;br /&gt;
=== Oszillogramme ===&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Phasen_PWM.png|300px]]&lt;br /&gt;
&lt;br /&gt;
Die drei Phasen während dem geregelten Betrieb, die BEMF ist sehr schön zu erkennen (immer zwischen den Zuständen &amp;quot;PWM&amp;quot; und &amp;quot;LOW&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Phasen_Vollgas.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So sehen die drei Phasen bei Vollgas aus (100% PWM). Die BEMF ist jetzt sogar so steil, dass man zwischen dieser Aufnahme und dem Diagramm oben ([[#Ansteuerung]]) eigentlich kein Unterschied mehr erkennen kann!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_BEMF_richtig.png|300px]]&lt;br /&gt;
&lt;br /&gt;
* Gelb: Phase A, BEMF sehr schön erkennbar&lt;br /&gt;
* Blau: Mittelpunktspannung&lt;br /&gt;
* Rot: BEMF von Phase A (nach der BEMF-Schaltung!)&lt;br /&gt;
* Grün: Komparator-Interrupts (steigende Flanke) Jeder dritte Interrupt gehört zur Phase A, die anderen Interrupts stammen von den anderen Phasen, die nicht auf dem Bild zu sehen sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_BEMF_falsch.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So kann z.B. die BEMF während der Zwangskommutierung aussehen. Dadurch werden auch zu viele Komparator-Interrupts (Grün, jede Flanke) ausgelöst. Kein schöner Anblick...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Anlauf_1.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So sieht der Anlaufvorgang bei einem gekauften Regler aus. eine extrem kurze Geschichte im Vergleich mit meinen paar Umdrehungen mit Zwangskommutierung. Wer kennt das Geheimnis?&lt;br /&gt;
&lt;br /&gt;
=== Layouts ===&lt;br /&gt;
&lt;br /&gt;
Als Anregung, wie so ein Regler aussehen könnte (nur 40x26mm klein, inklusive Optokoppler, drei Treibern und drei schönen Stecker!):&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Eagle3d_top_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Eagle3d_bot_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
Der HCPL-0600 auf der Unterseite ist übrigens ein Optokoppler um das PPM-Eingangssignal galvanisch zu entkoppeln. Ist nicht zwingend nötig, war aber grad Platz da... :-)&lt;br /&gt;
&lt;br /&gt;
== Siehe Auch ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/248509 Diskussion zum Artikel]&lt;br /&gt;
* [[BLDC Demo Board]]&lt;br /&gt;
* [[Treiber]]&lt;br /&gt;
* [[Mosfet-Übersicht]]&lt;br /&gt;
* [[Leiterbahnbreite]] Unbedingt beachten bei grösseren Strömen!&lt;br /&gt;
* [[Kühlkörper]] Bei sehr hohen Strömen evtl. nötig&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.mikrokopter.de/ucwiki/BrushlessCtrl BrushlessCtrl vom Mikrokopter]&lt;br /&gt;
* [http://svn.mikrokopter.de/listing.php?repname=BL-Ctrl&amp;amp; Software vom Mikrokopter Brushless-Regler]&lt;br /&gt;
* [http://home.versanet.de/~b-konze/ Die Seite von B. Konze, einer der Pioniere in diesem Bereich]&lt;br /&gt;
* [http://www.rcgroups.com/forums/showthread.php?t=1513678 Ein Thema auf rcgroups.com (Englisch) wo einige käuflichen Regler näher angeschaut wurden und eine eigene Firmware angeboten wird]&lt;br /&gt;
* [http://rmmx.gmxhome.de/bldchv/start.html Ein Regler-Projekt für etwas grössere Motoren]&lt;br /&gt;
* [http://www.fc00.de/quadrokopter_6_kw.htm Regler für sehr grosse Motoren]&lt;br /&gt;
* [http://ww1.microchip.com/downloads/en/AppNotes/01083a.pdf Appnote AN1083 von Microchip, sehr detailliert]&lt;br /&gt;
* [http://www.atmel.com/Images/doc8012.pdf AppNote AVR444 von Atmel]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Motoren]]&lt;/div&gt;</summary>
		<author><name>46.128.38.250</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Brushless-Controller_f%C3%BCr_Modellbaumotoren&amp;diff=66428</id>
		<title>Brushless-Controller für Modellbaumotoren</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Brushless-Controller_f%C3%BCr_Modellbaumotoren&amp;diff=66428"/>
		<updated>2012-05-19T11:57:29Z</updated>

		<summary type="html">&lt;p&gt;46.128.38.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Im Internet gibt es einige grundlegende Informationen zur Funktionsweise und Ansteuerung von Brushless-Motoren (BLDC). Für die Entwicklung eines solchen Reglers findet man aber nur wenig richtig detaillierte Informationen und Erfahrungsberichte. In diesem Artikel sollen genau diese Lücken geschlossen werden. Es soll hier aber kein fertiges Produkt (Schaltplan + Layout + Software) angeboten werden. Viel mehr soll es die Eigenentwicklung unterstützen, Ideen und Erfahrungen anbieten.&lt;br /&gt;
&lt;br /&gt;
An dieser Stelle weise ich noch darauf hin, dass man bei den [[#Weblinks]] noch einige sehr gute Informationen findet! Es gibt dort Hardware und Software, es lohnt sich die Links mal anzuschauen.&lt;br /&gt;
&lt;br /&gt;
==== Um welche Motoren geht es genau? ====&lt;br /&gt;
&lt;br /&gt;
Es geht hier um die sogenannten elektrisch kommutierten bürstenlosen Gleichstrommotoren (BLDC) aus dem Modellbaubereich. &lt;br /&gt;
&lt;br /&gt;
Deren Eigenschaften sind:&lt;br /&gt;
* Haben drei Anschlüsse für die drei Phasen, ansonsten sind keine weiteren Anschlüsse vorhanden&lt;br /&gt;
* Werden in der Regel mit LiPo Akkus versorgt&lt;br /&gt;
* Leistung im Bereich von ca. 100W bis 2kW&lt;br /&gt;
* Spannungen im Bereich von ca. 10 bis 50V&lt;br /&gt;
* Ströme im Bereich von ca. 5 bis 120A&lt;br /&gt;
&lt;br /&gt;
==== Um welche Motoren geht es hier nicht? ====&lt;br /&gt;
&lt;br /&gt;
* Motoren mit Hallsensoren für die Rückmeldung&lt;br /&gt;
* Festplattenmotoren&lt;br /&gt;
&lt;br /&gt;
Unter Umständen kann aber dieser Artikel auch für solche Motoren nützlich sein.&lt;br /&gt;
&lt;br /&gt;
== Funktionsweise dieser Motoren ==&lt;br /&gt;
&lt;br /&gt;
=== Ansteuerung ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:BLDC_Spannungs_Diagramm.png|thumb|right|250px|Ansteuerung der 3 Phasen]]&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich werden die 3 Phasen nacheinander bestromt, die Phasenspannungen wären also drei um 120° phasenverschobene Rechteckspannungen. Ein sinusförmiger Drehstrom ist nicht nötig, es genügen Rechteckspannungen. Mit einer Raumzeigermodulation könnte man die Stromaufnahme und die Geräuschentwicklung zwar noch verringern, macht die Ansteuerung aber einiges aufwändiger. Sogar die käuflichen Regler arbeiten nur mit Rechtecksignalen, zumindest die die ich kenne. &lt;br /&gt;
&lt;br /&gt;
Dabei gibt es für jede Phase die Zustände „Low“, „High“ und „Floating“. Low bedeutet 0V (GND), High entspricht der Versorgungsspannung und Floating ist keines von beidem, die Phase „hängt in der Luft“. Bei „High“ wird aber noch der Mittelwert der Spannung per PWM eingestellt, über das Tastverhältnis wird schlussendlich die Drehzahl verändert! Dazu aber später mehr.&lt;br /&gt;
&lt;br /&gt;
In der Grafik rechts kann man den Spannungsverlauf sehr gut erkennen. Das Diagramm zeigt aber nur den theoretischen Verlauf der Spannungen, wobei die gestrichelten Linien den Zustand &amp;quot;floating&amp;quot; symbolisieren. Dies kann man in einem Diagramm ja nicht wirklich darstellen, das ist einfach symbolisch gemeint. Interessanterweise sehen die Spannungen aufgrund der BEMF aber tatsächlich ziemlich ähnlich aus wie im Diagramm!&lt;br /&gt;
&lt;br /&gt;
=== Die 6 Zustände ===&lt;br /&gt;
&lt;br /&gt;
Wie man erkennen kann, werden 6 Zustände gebraucht, die sich dann immer wiederholen. Die Kommutierung ist also einfach ein Weiterschalten des Zustandes. &lt;br /&gt;
&#039;&#039;Diese 6 Zustände sind nicht mit den drei Zuständen von oben (High, Low, Floating) zu verwechseln, das ist ein anderes Thema!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In einer Tabelle dargestellt würde das folgendermassen aussehen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Zustand || Phase A || Phase B || Phase C || Stromfluss || Komparator-Eingänge&lt;br /&gt;
|-&lt;br /&gt;
| 1 || PWM || Floating || GND || A --&amp;gt; C || MITTEL &amp;lt;--&amp;gt; NULL_B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Floating || PWM || GND || B --&amp;gt; C || MITTEL &amp;lt;--&amp;gt; NULL_A&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GND || PWM || Floating || B --&amp;gt; A || MITTEL &amp;lt;--&amp;gt; NULL_C&lt;br /&gt;
|-&lt;br /&gt;
| 4 || GND || Floating || PWM || C --&amp;gt; A || MITTEL &amp;lt;--&amp;gt; NULL_B&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Floating || GND || PWM || C --&amp;gt; B || MITTEL &amp;lt;--&amp;gt; NULL_A&lt;br /&gt;
|-&lt;br /&gt;
| 6 || PWM || GND || Floating || A --&amp;gt; B || MITTEL &amp;lt;--&amp;gt; NULL_C&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Hinweise:&lt;br /&gt;
* Die Nummern in der ersten Spalte entsprechen genau den sechs Zuständen, die auch im obigen Diagramm nummeriert sind (Alle 6 Zustände zusammen bilden einen Zyklus, wie es auch im Diagramm dargestellt ist)&lt;br /&gt;
* Den Inhalt der letzten Spalte wird später noch erläutert. Die Bezeichnungen beziehen sich auf die [[#BEMF-Schaltung]].&lt;br /&gt;
&lt;br /&gt;
=== Einsatz der BEMF ===&lt;br /&gt;
Das schaut bis jetzt eigentlich wie ein Synchronmotor oder Schrittmotor aus, was ein BLDC im Prinzip auch ist.  &lt;br /&gt;
&lt;br /&gt;
Wie schon erwähnt wurde, wird ein BLDC elektronisch kommutiert. Das heisst, die Kommutierung wird nicht einfach stur vorgegeben, sondern es wird immer Rücksicht auf die Ankerposition genommen. Dazu muss man allerdings wissen, wann man die Kommutierung genau auslösen soll. &lt;br /&gt;
&lt;br /&gt;
Dieses Verfahren heißt Block-Kommutierung und ist ein Kompromiss aus Aufwand und Ergebnis:&lt;br /&gt;
Idealerweise werden die Ströme im Stator so eingeprägt, dass der Statorfluss dem Rotorfluss immer um 90° vorauseilt. Nur so wir das ideale Drehmoment erzeugt (siehe Literatur zur permanenterregten Synchronmaschine). Allerdings hat dieses Verfahren, auch Feldorientierte Regelung oder Vektor-Regelung genannt, den Nachteil, dass meistens teure Positionssensorik für den Rotor nowendig ist und auch die nötige Rechenleistung stark ansteigt. Die komplette Regelung muss für jede PWM-Periode gerechnet werden, damit sich der Aufwand lohnt. &lt;br /&gt;
Im Fall der Block-Kommutierung ist der ideale Kommutierungszeitpunkt also der, bei dem das Stator-Feld dem Rotor-Feld im Mittel um 90 ° vorauseilt. Dieser ideale Kommutierungszeitpunkt ist wegen der als konstant angenommenen Rechenzeit für die Kommutierung drehzahlabhängig.&lt;br /&gt;
&lt;br /&gt;
Zur Erreichung einer höheren Maximaldrehzahl kann das Rotorfeld durch das Statorfeld im sogenannten Feldschwäch-Betrieb geschwächt werden. Es ergeben sich Feldschwäch-(Blind)ströme im Bereich der Nennströme.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich kann auch ein BLDC nicht ohne Kenntnis der Lage des Rotors kommutiert werden. Und hier kommt die sogenannte Back Electromotive Force (BEMF) zum Einsatz. Von den drei Phasen liegt ja zu jedem Zeitpunkt genau eine Phase in der Luft wie man am Diagramm oben erkennen kann. Aufgrund des drehenden Magnetfeldes im Motor wird an dieser Phase nun eine Spannung induziert. Und genau diese induzierte Spannung gibt nun Auskunft darüber, in welchem Winkel sich der Anker befindet, und daraus kann man dann auch den Zeitpunkt der nächsten Kommutierung bestimmen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich wird aber auch noch die Sternmittelpunktspannung der drei Phasen benötigt, welche aber leider nicht direkt zur Verfügung steht. Das ist aber kein Problem, mit drei Widerständen kann man sich die selber erzeugen (siehe [[#BEMF-Schaltung]]).&lt;br /&gt;
&lt;br /&gt;
Jetzt sollten die BEMF-Spannungen die Sternmittelpunktspannung ständig kreuzen, was man dann mit einem Komparator erfassen kann. Und den Interrupt, den der Komparator auslöst, ist nun verantwortlich für die nächste Kommutierung.&lt;br /&gt;
Der Komparator wird natürlich nacheinander mit den drei Phasen gefüttert, es darf immer nur die Phase an den Komparator angeschlossen sein, die auch in der Luft hängt! In der Tabelle [[#Die 6 Zustände]] sieht man, welche zwei Spannungen der Komparator jeweils vergleichen muss.&lt;br /&gt;
&lt;br /&gt;
Als Komparator kann man übrigens den integrierten nehmen, den es in den AVRs gibt. Diese (alle?) haben auch den benötigten Multiplexer, um zwischen den drei Analogquellen wählen zu können. Näheres dazu im Abschnitt [[#Software]].&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Leistungsteil ===&lt;br /&gt;
&lt;br /&gt;
==== Treiber ====&lt;br /&gt;
&lt;br /&gt;
Um die drei notwendigen Zustände (&#039;&#039;Low&#039;&#039;, &#039;&#039;High&#039;&#039; und &#039;&#039;Floating&#039;&#039;) für jede der drei Phasen realisieren zu können, werden drei Halbbrücken mit Mosfets benötigt. Hier gibt es dann auch schon mehrere Varianten, wie man das aufbauen kann. Grundsätzlich muss man sich mal überlegen ob fertige FET-Treiber oder diskrete Treiber verwendet werden sollen. Die FET-Treiber haben einige sehr schöne Vorteile, deshalb sollte man diese meiner Meinung nach bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Die Vorteile wären:&lt;br /&gt;
&lt;br /&gt;
* Integrierter Kurzschlussschutz mit dead time, ein Softwarefehler kann die FETs nicht zerstören. Das kann in der Entwicklungsphase sehr von Vorteil sein :-)&lt;br /&gt;
* Die FETs können mit ordentlicher Geschwindigkeit geschaltet werden, und die Mikrocontroller-Ports werden trotzdem nicht stark belastet. So kann die Wärmeentwicklung der FETs noch etwas reduziert werden.&lt;br /&gt;
* Bei Treibern die mit nur einem Eingang zwischen Lowside und Highside Mosfets toggeln (z.B. IR2104), ist der sogenannte „aktiver Freilauf“ bereits in Hardware realisiert und ermöglicht so mit wenig Aufwand eine extrem niedrige Erwärmung der Mosfets. Das ermöglicht schon sehr grosse Ströme auch ohne Kühlkörper!&lt;br /&gt;
* Es können günstigere Mosfets verwendet werden, es müssen keine TTL-Kompatible FETs sein. Auch ist eine niedrige Gatekapazität nicht so von Bedeutung wie bei direkter Ansteuerung mit einem Mikrocontroller.&lt;br /&gt;
* Je nach dem welchen Treiber man verwendet, kann der Softwareaufwand und die Fehleranfälligkeit deutlich reduziert werden.&lt;br /&gt;
&lt;br /&gt;
Nachteile von Treiber sind:&lt;br /&gt;
&lt;br /&gt;
* Mehr Bauteile auf der Platine.&lt;br /&gt;
* Vermutlich insgesamt etwas teurer, auch wenn die FETs günstiger sind.&lt;br /&gt;
* Bei vielen Treibern ist eine Minimalspannung von ca. 10V notwendig, damit sie funktionieren. Bei einem fast leeren 3S LiPo Akku könnte das vielleicht schon kritisch werden. Auch darf z.B. beim IR2104 eine Spannung von 20V nicht überschritten werden. Daher kommt (ohne StepUp und StepDown Wandler) eigentlich fast nur noch ein 4S Akku in Frage. Möchte man einen grösseren Eingangsspannungsbereich haben muss man noch entsprechende Spannungsregler einbauen.&lt;br /&gt;
&lt;br /&gt;
Ich persönlich habe es schon mit einem IR2104S probiert, dieser erscheint mir sehr geeignet für diese Aufgabe. Ich betreibe ihn mit einem 4S LiPo, damit läuft das Teil perfekt. Kann ich nur weiterempfehlen!&lt;br /&gt;
&lt;br /&gt;
==== Beispielschaltung ====&lt;br /&gt;
[[Datei:BLDC_Leistungsteil_1.png|thumb|right|300px|Beispiel einer Halbbrücke inklusive Strommessung]]&lt;br /&gt;
Hier ein Beispiel, wie der Leistungsteil einer Phase aussehen könnte.&lt;br /&gt;
&lt;br /&gt;
Für die exakte Beschaltung der Treiber muss man natürlich dessen Datenblatt studieren!&lt;br /&gt;
&lt;br /&gt;
Hier sieht man auch gleich noch die Strommessung, die man natürlich nicht für jede Phase einzeln aufbauen muss. Man kann sie sogar ganz weglassen, sie könnte aber nützlich sein um eine Überlast des Motores erkennen zu können.&lt;br /&gt;
&lt;br /&gt;
Der Widerstand R20 ist dazu da, dass auf dem Treiber das PWM-Signal liegt, sobald die Leitung „IN_A“ in der Luft hängt (uC Pin als Eingang definiert). So wird nur ein einziger PWM-Ausgang vom Mikrocontroller benötigt für alle drei Phasen, erfordert also kein Soft-PWM oder sonst irgend ein Murks. Diese Schaltung habe ich übrigens beim Mikrokopter-Projekt abgeschaut.&lt;br /&gt;
&lt;br /&gt;
Übrigens muss an die Versorgung unbedingt noch ein grosser Elko gehängt werden, am besten möglichst nahe an die Mosfets (keine langen Leitungen zwischen Elko und Mosfets). Die erforderliche Kapazität hängt davon ab, wieviel Strom der Motor braucht. bei kleinen bis mittleren Motoren sollten so 220uF bis 680uF ausreichend sein.&lt;br /&gt;
&lt;br /&gt;
=== BEMF-Schaltung ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:BLDC_BEMF_schaltung.png|thumb|right|300px|BEMF-Schaltung]]&lt;br /&gt;
&lt;br /&gt;
Ein wichtiger Teil ist aber auch die BEMF-Schaltung. Dabei wird häufig die Schaltung vom Mikrokopter eingesetzt (siehe Schaltung rechts).&lt;br /&gt;
&lt;br /&gt;
Die Schaltung besteht erstmal aus drei Spannungsteilern, die die Phasenspannungen auf ein Spannungsniveau heruntersetzen, das man auf die Mikrokontrollereingänge legen darf. Keramikkondensatoren glätten diese Spannungen, weil die aufgrund der PWM sonst sehr stark ausschlagen. Dann gehen diese drei Spannungen (&#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039;) auf drei ADC-Eingänge des Mikrocontrollers.&lt;br /&gt;
&lt;br /&gt;
Und dann sind da noch die drei Widerstände, die aus den Spannungen &#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039; einen virtuellen Sternmittelpunkt bilden. Diese Mittelpunktspannung (&#039;&#039;MITTEL&#039;&#039;) kommt dann auf den Komparatoreingang &#039;&#039;AIN0&#039;&#039; vom AVR. Diese Spannung soll der Komparator später dann mit jeweils einer der Spannungen &#039;&#039;NULL_A&#039;&#039;, &#039;&#039;NULL_B&#039;&#039; und &#039;&#039;NULL_C&#039;&#039; vergleichen um den Kommutierungszeitpunkt bestimmen zu können.&lt;br /&gt;
&lt;br /&gt;
Man kann die Widerstands-/ und Kapazitätswerte auch noch anpassen. Bei höheren Eingangsspannungen muss man darauf achten, dass die Eingänge vom AVR keine zu hohe Spannung abkriegen! Ein Regler, den ich gekauft habe, hat einiges höhere Widerstandswerte und kommt sogar ohne Kondensatoren aus. Hier hat man also durchaus noch Spielraum um ein bisschen zu tüfteln, für den Anfang ist die abgebildete Schaltung aber bestens geeignet.&lt;br /&gt;
&lt;br /&gt;
=== Mikrocontroller ===&lt;br /&gt;
&lt;br /&gt;
Als Mikrocontroller sind viele Typen aus der AVR-Serie geeignet. Bei der BrushlessCtrl wird zum Beispiel ein ATMega168 eingesetzt. Mit diesem habe ich auch mal angefangen, der scheint wirklich gut geeignet zu sein. Es reicht aber auch ein ATMega88 wenn man nicht alle möglichen Protokolle und Ansteuerungsarten (I2C, SPI, PPM) gleichzeitig einbauen will.&lt;br /&gt;
&lt;br /&gt;
Viele Regler verwenden auch einen AT90PWM, vorallem wenn mehrere PWM-Kanäle gebraucht werden.&lt;br /&gt;
&lt;br /&gt;
Übrigens wird bei käuflichen Reglern extrem häufig ein ATMega8 eingesetzt! Wenn man nur Software entwickeln möchte kann man auch einen solchen Regler kaufen und das eigene Programm aufspielen. Bei den [[#Weblinks]] findet man dazu auch noch Informationen.&lt;br /&gt;
&lt;br /&gt;
Um eine Raumzeigermodulation zu implementieren wird dann aber vermutlich schon ein 32-Bit Mikrocontroller nötig sein. Aber wie schon erwähnt ist für ein Modellbaumotor eine Raumzeigermodulation keinesfalls ein must-have.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Bei der Software kommt es jetzt natürlich sehr stark darauf an, wie die Hardware aufgebaut ist. Ich möchte hier aber nicht auf jede Variante eingehen, das gäbe viel zu viel Arbeit. Auch will ich ja kein fertiger Code bereitstellen, sondern nur Hinweise und Tipps geben. Wer nicht selber programmieren will, der kann ja mal die Mikrokopter-Firmware herunterladen, die älteren Versionen davon gibt es auf der Mikrokopter-Seite zum downloaden.&lt;br /&gt;
&lt;br /&gt;
Wichtig sind auf jeden Fall [[#Die 6 Zustände]]. Der Mikrocontroller muss die Phasen jeweils nacheinander so wie in der Tabelle ansteuern. Das ist soweit ja kein Problem, schwierig ist aber immer der richtige Zeitpunkt für die Kommutierung zu finden.&lt;br /&gt;
&lt;br /&gt;
Falls man einen IR2104 oder einen ähnlichen Treiber verwendet, würde die Software ungefähr so aussehen:&lt;br /&gt;
&lt;br /&gt;
* Beim Programmstart wird schonmal der PWM-Ausgang mit einem Timer aktiviert. Die Frequenz liegt normalerweise so im Bereich 12 bis 25kHz. Ich selber verwende 20kHz, da hört man dann auch dieses Pfeifen nicht mehr.&lt;br /&gt;
* Der Interrupt vom Analogkomparator muss aktiviert werden, um die Kommutierungszeitpunkte bestimmen zu können.&lt;br /&gt;
* Dann habe ich eine Funktion, welche den Zustand (1 bis 6) eins weiterschaltet und die Ausgänge entsprechend setzt. Dabei werden die Pins, die das PWM-Signal enthalten sollen, einfach als Eingang definiert, wie ich schonmal erwähnte.&lt;br /&gt;
* Wichtig ist ausserdem, dass bei jeder Kommutierung auch noch der richtige ADC-Kanal auf den Komparator geleitet wird per Multiplexer. Dieser Kanal wird bei jeder Kommutierung eins weitergeschaltet.&lt;br /&gt;
* Danach muss nur noch gewartet werden bis der Analogkomparator einen Interrupt auslöst. Sobald dies geschieht, wird die nächste Kommutierung ausgelöst, und das Spiel beginnt wieder von vorne.&lt;br /&gt;
&lt;br /&gt;
Ich glaube aber, dass dies noch nicht die ganz richtige Art ist, wie man die Kommutierung auslöst. Ich denke, man müsste nach einem Interrupt eine gewisse Zeit warten (je nach Kommutierungswinkel oder wie das heisst) und erst kurz vor dem nächsten Interrupt die Kommutierung auslösen. Also quasi immer einen Zustand später. Dazu muss aber die Verzögerungszeit ständig ausgerechnet werden, damit die auch bei jeder Drehzahl stimmt. Ich habe es selber noch nicht so implementiert, kann daher nicht sagen ob das so dann richtig funktioniert. &#039;&#039;&#039;Falls hier jemand besser Bescheid weiss, wäre es cool wenn man das hier noch ergänzen könnte.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Laut Literatur liegt der optimale Kommutierungszeitpunkt 30° nach dem Nulldurchgang der Spannung am nicht beschalteten Eingang. Die naheliegendste Möglichkeit wäre also die Zeit, die bei der aktuellen Drehzahl für eine Umdrehung benötigt wird, durch zwölf zu dividieren und so lange bis zur Kommutierung zu warten.&lt;br /&gt;
&lt;br /&gt;
Ausserdem scheint es auch Regler zu geben, die eine Kommutierung nicht mit dem Analogkomparator erfassen, sondern direkt mit ADC-Wandlungen. Dazu weiss ich aber leider auch nichts näheres, deshalb auch hier: &#039;&#039;&#039;Wenn jemand weiss, was es damit auf sich hat, bitte melden.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Drehzahl des Motores lässt sich jetzt ganz bequem ändern, indem man den Duty-Cycle des PWM-Signales verändert. Der Motor beschleunigt bzw. bremst dann von alleine.&lt;br /&gt;
&lt;br /&gt;
=== Anlauf ===&lt;br /&gt;
&lt;br /&gt;
So, das war jetzt die Beschreibung für einen Motor, der bereits läuft. &#039;&#039;&#039;Bis&#039;&#039;&#039; der Motor allerdings mal dreht, muss man anders vorgehen, weil der stillstehende Motor ja keine Komparator-Interrupts auslöst, da keine BEMF vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Daher muss man den Motor zuerst mit einem starren Drehfeld auf eine gewisse Drehzahl beschleunigen, wie bei einem Schrittmotor. Sobald eine genügend hohe Drehzahl erreicht wurde, kann man in den geregelten Betrieb schalten. Am besten schaltet man dazu einfach alle Phasen ab und aktiviert den Komparator. Sobald der erste Interrupt vom Komparator ausgelöst wird, werden die Phasen wieder eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
Der ganze Startvorgang ist aber schon eine Wissenschaft für sich. Es braucht (nach meiner Erfahrung) viel Zeit und Nerven, bis alles richtig funktioniert. Man kann aber am Anfang den Motor auch von Hand anwerfen, das geht viel einfacher als mit einer Zwangskommutierung. Ein Oszilloskop ist eigentlich auch absolut notwendig, um analysieren zu können was der Regler und die BEMF genau macht. &lt;br /&gt;
&lt;br /&gt;
Ganz wichtig aber an dieser Stelle: &#039;&#039;&#039;Wenn der Motor mit einem starren Drehfeld angesteuert wird, sieht die BEMF alles andere als schön aus!&#039;&#039;&#039; Das liegt daran, dass der Motor bei jeder Kommutierung beschleunigt, und danach wieder abgebremst wird, der Motor läuft einfach nicht „rund“. Wenn ihr also irgendwas komisches auf dem Oszilloskop seht, ist das kein Fehler in eurer Schaltung, das ist normal bei Zwangskommutierung!&lt;br /&gt;
&lt;br /&gt;
Wenn Ihr die BEMF auf dem Oszilloskop anschauen wollt, könnt Ihr entweder den Motor einfach von Hand drehen, oder ihr dreht den Motor mit Zwangskommutierung hoch, und schaltet dann alle Phasen ab (nicht auf GND, in der Luft hängend). Direkt nach dem Abschalten der Phasen sollte die BEMF einen relativ schönen Drehstrom zeigen (muss ich selbst noch kontrollieren ob das wirklich der Fall ist :-) )&lt;br /&gt;
&lt;br /&gt;
Bis jetzt habe ich es mit dieser Variante aber noch nicht so richtig geschafft, einen brauchbaren Anlaufvorgang hinzukriegen. Ich glaube auch, dass gekaufte Regler das nicht so machen. Diese scheinen nur einen kräftigen Strom auf eine Phase zu geben, und werten dann die entstandene BEMF aus, aus der dann berechnet werden kann, welche Phase als nächstes bestromt werden muss. So richtig habe ich das aber noch nicht angeschaut, &#039;&#039;&#039;vielleicht weiss hier jemand besser Bescheid und könnte es hier beschreiben?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Schnittstellen ===&lt;br /&gt;
&lt;br /&gt;
Man kann nun den Sollwert der Drehzahl wahlweise über einen PPM-Eingang, über UART, SPI oder I2C vorgeben. Das überlasse ich aber jedem selber, es kommt natürlich darauf an wo der Regler schlussendlich eingesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
== Bildmaterial ==&lt;br /&gt;
=== Oszillogramme ===&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Phasen_PWM.png|300px]]&lt;br /&gt;
&lt;br /&gt;
Die drei Phasen während dem geregelten Betrieb, die BEMF ist sehr schön zu erkennen (immer zwischen den Zuständen &amp;quot;PWM&amp;quot; und &amp;quot;LOW&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Phasen_Vollgas.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So sehen die drei Phasen bei Vollgas aus (100% PWM). Die BEMF ist jetzt sogar so steil, dass man zwischen dieser Aufnahme und dem Diagramm oben ([[#Ansteuerung]]) eigentlich kein Unterschied mehr erkennen kann!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_BEMF_richtig.png|300px]]&lt;br /&gt;
&lt;br /&gt;
* Gelb: Phase A, BEMF sehr schön erkennbar&lt;br /&gt;
* Blau: Mittelpunktspannung&lt;br /&gt;
* Rot: BEMF von Phase A (nach der BEMF-Schaltung!)&lt;br /&gt;
* Grün: Komparator-Interrupts (steigende Flanke) Jeder dritte Interrupt gehört zur Phase A, die anderen Interrupts stammen von den anderen Phasen, die nicht auf dem Bild zu sehen sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_BEMF_falsch.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So kann z.B. die BEMF während der Zwangskommutierung aussehen. Dadurch werden auch zu viele Komparator-Interrupts (Grün, jede Flanke) ausgelöst. Kein schöner Anblick...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Oszillogramm_Anlauf_1.png|300px]]&lt;br /&gt;
&lt;br /&gt;
So sieht der Anlaufvorgang bei einem gekauften Regler aus. eine extrem kurze Geschichte im Vergleich mit meinen paar Umdrehungen mit Zwangskommutierung. Wer kennt das Geheimnis?&lt;br /&gt;
&lt;br /&gt;
=== Layouts ===&lt;br /&gt;
&lt;br /&gt;
Als Anregung, wie so ein Regler aussehen könnte (nur 40x26mm klein, inklusive Optokoppler, drei Treibern und drei schönen Stecker!):&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Eagle3d_top_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
[[Datei: BLDC_Eagle3d_bot_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
Der HCPL-0600 auf der Unterseite ist übrigens ein Optokoppler um das PPM-Eingangssignal galvanisch zu entkoppeln. Ist nicht zwingend nötig, war aber grad Platz da... :-)&lt;br /&gt;
&lt;br /&gt;
== Siehe Auch ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/248509 Diskussion zum Artikel]&lt;br /&gt;
* [[BLDC Demo Board]]&lt;br /&gt;
* [[Treiber]]&lt;br /&gt;
* [[Mosfet-Übersicht]]&lt;br /&gt;
* [[Leiterbahnbreite]] Unbedingt beachten bei grösseren Strömen!&lt;br /&gt;
* [[Kühlkörper]] Bei sehr hohen Strömen evtl. nötig&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.mikrokopter.de/ucwiki/BrushlessCtrl BrushlessCtrl vom Mikrokopter]&lt;br /&gt;
* [http://svn.mikrokopter.de/listing.php?repname=BL-Ctrl&amp;amp; Software vom Mikrokopter Brushless-Regler]&lt;br /&gt;
* [http://home.versanet.de/~b-konze/ Die Seite von B. Konze, einer der Pioniere in diesem Bereich]&lt;br /&gt;
* [http://www.rcgroups.com/forums/showthread.php?t=1513678 Ein Thema auf rcgroups.com (Englisch) wo einige käuflichen Regler näher angeschaut wurden und eine eigene Firmware angeboten wird]&lt;br /&gt;
* [http://rmmx.gmxhome.de/bldchv/start.html Ein Regler-Projekt für etwas grössere Motoren]&lt;br /&gt;
* [http://www.fc00.de/quadrokopter_6_kw.htm Regler für sehr grosse Motoren]&lt;br /&gt;
* [http://ww1.microchip.com/downloads/en/AppNotes/01083a.pdf Appnote AN1083 von Microchip, sehr detailliert]&lt;br /&gt;
* [http://www.atmel.com/Images/doc8012.pdf AppNote AVR444 von Atmel]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Motoren]]&lt;/div&gt;</summary>
		<author><name>46.128.38.250</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:Platinenhersteller&amp;diff=65979</id>
		<title>Diskussion:Platinenhersteller</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:Platinenhersteller&amp;diff=65979"/>
		<updated>2012-05-01T10:53:00Z</updated>

		<summary type="html">&lt;p&gt;46.128.38.250: Neuer Abschnitt /* Vorschlag für &amp;quot;Deutschland sehr günstige&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Werbung ==&lt;br /&gt;
&lt;br /&gt;
Kann das mal ein &amp;quot;Angemeldeter&amp;quot; entfernen?&lt;br /&gt;
http://www.mikrocontroller.net/wikisoftware/index.php?title=Platinenhersteller&amp;amp;diff=58254&amp;amp;oldid=prev&lt;br /&gt;
&lt;br /&gt;
Siehe auch hier (da braucht es einen Moderator): http://www.mikrocontroller.net/wikisoftware/index.php?title=Benutzer:Aetzwerk&amp;amp;diff=58255&amp;amp;oldid=prev&lt;br /&gt;
&lt;br /&gt;
Danke. (IP - 01.07.11)&lt;br /&gt;
&lt;br /&gt;
Da die nur an gewerbliche Kunden liefern, ist das Angebot (mal von der Lobhudelei abgesehen) in dieser Liste wohl wirklich fehlplatziert.&lt;br /&gt;
&lt;br /&gt;
== Diverses ==&lt;br /&gt;
&lt;br /&gt;
kurzes lob/kritik und beschreibung der einzelnen firmen helfen weiter, siehe elektronik-versender&lt;br /&gt;
vielleicht aphabetische reihenfolge ?&lt;br /&gt;
&lt;br /&gt;
Stimme ich voll zu. Interessant wäre allerdings auch eine Liste der Features, d.h. wie viele Layers, wie klein der Abstand sein darf etc.&lt;br /&gt;
&lt;br /&gt;
== Bilex ==&lt;br /&gt;
&lt;br /&gt;
ad bilex: Ohne jetzt jemandem was unterstellen zu wollen oder paranoid zu sein, aber es ist doch seltsam, wenn in einem deutschsprachigen Wiki die Lobeshymnen für diesen bulgarischen Hersteller ausgerechnet von einer bulgarischen IP-Adresse kommen.&lt;br /&gt;
&lt;br /&gt;
Betreffend Bilex: Die letzten Änderungen, die vor allem Kritik an Bilex entfernt haben, wurden von einer IP-Adresse aus Bulgarien vorgenommen. Das erweckt natürlich einen Verdacht. Darum bitte ich das nachzuprüfen und zu korrigieren! Danke!&lt;br /&gt;
&lt;br /&gt;
Zu Bilex: Meine zweimalige Kritik an Bilex wurde entfernt und durch Rechtfertigungen in schlechtem Deutsch ersetzt. Dies deutet ja daraufhin, wer sich hier ins rechte Licht setzt. Wenn ich erst alles extra bestellen muß (Beschichtung, Fräsung, Bohrungen) was eigentlich als selbstverständlich vorauszusetzen ist, bleibe ich lieber bei einem deutschen Hersteller und kann mich auf die Qualität verlassen. Diese Fehlversuche mit Bilex haben unserer Firma 4 Wochen Zeitverzug gekostet, da die gefertigten Leiterplatten nicht als Vorzeigeobjekt beim Kunden brauchbar waren.&lt;br /&gt;
----&lt;br /&gt;
Diese Änderungen wurden mit einer bulgarischen IP-Adresse vorgenommen. Noch Fragen?&lt;br /&gt;
--[[Benutzer:Andreas|Andreas]] 16:45, 5. M?2006 (CET)&lt;br /&gt;
&lt;br /&gt;
== Vorschlag für &amp;quot;Deutschland sehr günstige&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
Den Hersteller http://www.pcb-devboards.de hab ich nicht im Artikel gefunden, würde den aber gerne festhalten. Leider kann ich das nicht, weil der Artikel für nicht-angemeldete gesperrt ist?&lt;br /&gt;
&lt;br /&gt;
Min Leiterbahnbreite/Abstand: 0,2 mm&lt;br /&gt;
&lt;br /&gt;
Bohrungs-Durchmesser: 0.4 .. 5 mm, ab 5 mm wird gefräst, alle Bohrungen frei&lt;br /&gt;
&lt;br /&gt;
Restring: min 0.254 mm&lt;br /&gt;
&lt;br /&gt;
Platinen sind 2-Lagig und &#039;&#039;&#039;durchkontaktiert&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Preis: 195 x 90 mm: 20 Euro&lt;br /&gt;
&lt;br /&gt;
Ich bin nicht der Betreiber, finde das Angebot aber sehr günstig, weil alle Bohrungen enthalten sind und nicht zuletzt, weil die Platine durchkontaktiert ist!&lt;br /&gt;
&lt;br /&gt;
Was meint Ihr?&lt;/div&gt;</summary>
		<author><name>46.128.38.250</name></author>
	</entry>
</feed>