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

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=17401</id>
		<title>Roboterwettbewerbe</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=17401"/>
				<updated>2011-04-15T17:53:05Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: Termine aktualisiert, nicht aktive Wettbewerbe aussortiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf diese Seite werden die bekanntesten nationalen und internationalen Roboterwettbewerbe kurz vorgestellt.&lt;br /&gt;
&lt;br /&gt;
==Überblick==&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |''' Wettbewerb primär für'''||Schüler ||Studenten || Hobbyrobotiker ||1 Person || bis 5 Personen || mehr als 5 Personen || nächster Termin || Ort&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Eurobot|Eurobot]] || X || X ||  ||  ||  || X || 22. bis 27.06.2011 || Russland&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Carolo_Cup|Carolo Cup]] || || X || || || || X  || 07. / 08.02.2011  || Braunschweig&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Field_Robot_Event|Field Robot Event]] || || X || || || || X  || 30.6. - 02.07.2011 || Dänemark&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#FIRST_Lego_League|FIRST LEGO Leaue]] || X ||  ||  || ||  || X || 4. - 30.11. in 52 Regionen(Zentraleuropa) ||   &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboCup_Soccer|RoboCup Soccer]] || || X ||  ||  ||  || X   || 04. - 10.07.2011 || Istanbul&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotChallenge|RobotChallenge]] || || || X || X || || || 12. / 13.03.2011 || Wien&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#SPURT|SPURT]] || X || || ||  || X ||  || 20.05.2011 || Rostock&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ELROB|European Land Robot Trial (ELROB)]] ||  || X ||  || ||  || X  || 20. - 24.07.2011 || Leuven, Belgien&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ROBOCOM|ROBOCOM]] || X ||  ||  ||  || X || || 15.07.2011 || Gelsenkirchen&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotLiga|RobotLiga]] || || || X || X || || || keine nach 2007 bekannt ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboTest|RoboTest]] || || || X || X || || || keine nach 2008 bekannt ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboKing|RoboKing]] || X || || || || X || || keine nach 2008 bekannt ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#GSF_Robot_Contest|GSF Robot Contest]] ||  ||  || X ||X || X ||   || keine nach 2007 bekannt ||&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
= Aktuelle Wettbewerbe =&lt;br /&gt;
&lt;br /&gt;
==Eurobot==&lt;br /&gt;
&amp;quot;Seit 1998 ist Eurobot ein internationaler Roboterwettbewerb für Teams von Jugendlichen, Studenten und sonstigen an Robotern interessierten Menschen.&lt;br /&gt;
Eurobot findet stets in Europa statt, ist aber für alle Länder aller Kontinente zugänglich. Im Jahre 2004 nahmen insgesamt 250 Teams aus 21 Länder an diesem technisch/wissenschaftlichen Wettbewerb teil.&amp;quot; (zitiert von www.eurobot.org)&lt;br /&gt;
Aus jedem Land dürfen maximal drei Teams zu den internationalen Finalen fahren. Diese drei Mannschaften müssen sich in nationalen Vorausscheiden qualifizieren. Die Aufgabe wird jedes Jahr neu gestellt. Nur die Rahmenbedingungen bleiben gleich: Ein Match dauert nur 90 Sekunden, es ist also sowohl Schnelligkeit als auch eine intelligente Taktik und Sicherheit gefragt. Die Spielfläche ist etwa 2x3 Meter groß.&lt;br /&gt;
Eurobot findet seit 2005 jedes Jahr in einem anderen Land statt. Der Wettbewerb wird von einer großen Rahmenveranstaltung inklusive Vorträgen und vielen Attraktionen für die zahlreichen Zuschauer ergänzt.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.eurobot.org www.eurobot.org]&lt;br /&gt;
* [http://www.eurobot-deutschland.de www.eurobot-deutschland.de]&lt;br /&gt;
&lt;br /&gt;
==Carolo Cup==&lt;br /&gt;
Dieser Wettbewerb für Studenten findet an der TU Braunschweig statt. &lt;br /&gt;
Es treten autonome Modellfahrzeuge im Maßstab 1:10 gegeneinander an. Aufgaben sind das Fahren auf einem Rundkurs (dabei muss die Fahrbahnmarkierung z.B. mit Kameras erkannt werden) und das seitliche Einparken in einer vorgegebenen Parklücke.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.carolo-cup.de www.carolo-cup.de]&lt;br /&gt;
&lt;br /&gt;
==Field Robot Event==&lt;br /&gt;
Dieser Wettbewerb für Studenten findet auf einem Maisfeld statt. Die Roboter müssen den Maisreihen folgen und &amp;quot;Unkraut&amp;quot; erkennen, wobei es mehrere Schwierigkeitsgrade gibt (z.B. können einzelne Pflanzen fehlen, oder es gibt größere Unebenheiten im Boden).&lt;br /&gt;
2011 wird der Wettbewerb in Dänemark ausgetragen.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.fre2011.dk/ http://www.fre2011.dk/]&lt;br /&gt;
&lt;br /&gt;
==FIRST Lego League==&lt;br /&gt;
Bei der FIRST LEGO League (FLL) handelt es sich um einen internationalen Wettbewerb der von der Firma LEGO und der amerikanischen Stiftung FIRST (For Inspiration and Recognition of Science and Technology) veranstalltet wird. Er findet jährlich auf der ganzen Welt mit regionalen Runden statt und steht jedes Jahr unter einem neuen Motto. &lt;br /&gt;
&lt;br /&gt;
Der Wettbewerb beschäftigt sich immer mit aktuellen naturwissenschaftlichen Problemen, die gesellschaftlich relevant sind. Dabei sollen die Kinder nicht nur einen Roboter programmieren, der Aufgaben auf dem vorgegebenen Spielfeld erfüllt, sondern sich auch tiefgründig mit dem Wettbewerbsthema auseinandersetzen. Die Teilnehmer sollen einen Lösungsansatz für ein aktuelles Probleme erarbeiten, dass mit dem Wettbewerbsthema in Verbindung steht. 2010 heißt das Thema von FLL &amp;quot;Body Forward&amp;quot; und dabei dreht sich alles um Biomedizin.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Wettbewerb dürfen nur Roboter eingesetzt werden, die aus dem LEGO Mindstorms System bestehen. Der Wettbewerb richtet sich vornehmlich an junge Schüler, wie auch das gesamte Mindstorms System. Deshalb dürfen die Teilnehmer maximal 16 Jahre alt sein. Jedes Team wird von einem volljährigen Coach bei der Bewältigung der Aufgaben angeleitet. &lt;br /&gt;
&lt;br /&gt;
Die Wettbewerbsaufgaben werden immer Anfang September veröffentlicht, danach hat jedes Team ca. 8 Wochen Zeit seinen Roboter zu programmieren und den Forschungsauftrag zu erfüllen, um die Ergebnisse dann bei einem der Regionalwettbewerbe zu präsentieren.&lt;br /&gt;
 &lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.firstlegoleague.org/ www.firstlegoleague.org]&lt;br /&gt;
* [http://www.firstlegoleague.de/ www.firstlegoleague.de]&lt;br /&gt;
&lt;br /&gt;
==RoboCup Soccer==&lt;br /&gt;
Die Komplexität und Beliebtheit von Fußball (soccer) spielten wesentliche Rollen bei der Motivation der ersten RoboCupspiele Mitte der 90er Jahre. Die Dynamik und die Komplexität von Fußball birgt enorme Herausforderungen für Wissenschaftler, die sich mit der Entwicklung von autonomen Robotern in diesem Bereich beschäftigen: &lt;br /&gt;
&lt;br /&gt;
Individuelle Herausforderungen: jeder Agent/Roboter muss Objekte erkennen, sich selbst lokalisieren, navigieren und den Ball bewegen können. Zu klären sind Fragen wie: was ist in diesem Moment wichtig in meiner Wahrnehmung? Ist meine Position und die der anderen Mitspieler bekannt? &lt;br /&gt;
Kooperation von Agenten: in einer dynamischen Echtzeitumgebung kommt es nicht auf einen einzelnen Spieler an, sondern besonders auf das kooperative Spiel, bei dem auch die Kommunikation eine große Rolle spielt.&lt;br /&gt;
&lt;br /&gt;
Dynamische Echtzeitumgebung mit sich bewegenden Objekten, von denen einige intelligente Agenten sind, die gegen einen spielen. Diese Art von Umgebung ist z.B. auch im Straßenverkehr zu beobachten, wobei die anderen Verkehrsteilnehmer zwar keine Gegner sind, die meine Pläne durchkreuzen wollen, wo aber die Situationen beliebig komplex werden können.&lt;br /&gt;
RoboCupSoccer besteht aus fünf Ligen: der Simulationsliga, der Small-Size Liga, der Middle-Size Liga, der Sony Legged Liga, und der Humanoidliga. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robocup.org www.robocup.org]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==RobotChallenge==&lt;br /&gt;
Die RobotChallenge ist ein österreichischer Wettbewerb für selbstgebaute, autonome Roboter, dessen Ziel es ist für den kreativen Umgang mit innovativen Technologien zu begeistern. Experimente und praktische Erfahrungen lassen Teilnehmer und Zuschauer Wissenschaft hautnah erleben. Dieser Wettbewerb soll zeigen, wie man mit einfachen Mitteln, aber offenem Geiste und Phantasie spannende, zukunftstaugliche Lösungen finden kann. &lt;br /&gt;
Folgende Disiplienen wurden dort schon ausgetragen:&lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom'''&amp;lt;br&amp;gt;&lt;br /&gt;
Möglichst schnell muss einer schwarzen Linie auf weißem Untergrund entlang gefahren werden. Reglement im Wesentlichen wie bei RC'05. &lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom Enhanced'''&amp;lt;br&amp;gt;&lt;br /&gt;
Wie Parallel-Slalom, jedoch mit Erschwernissen: ein Tunnel, eine kurze Unterbrechung der Linie und ein Hindernis auf der Linie, das umfahren werden muss. &lt;br /&gt;
&lt;br /&gt;
'''Robot-Sumo'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter treten gegeneinander an und versuchen den jeweils anderen von einer runden Platte zu schieben. Die Platte ist schwarz, der Rand ist durch einen weissen Streifen markiert. Die Regeln entsprechen der internationalen Norm für autonomes Roboter-Sumo. &lt;br /&gt;
&lt;br /&gt;
'''Hindernislauf'''&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Infrarot-Leuchtturm mit definiertem Signal am Ende des Parcours ist möglichst rasch zu erreichen. Auf dem Weg befindliche Hindernisse müssen umfahren werden. Jedes Team kann alternativ auch einen eigenen Leuchtturm als Orientierungshilfe mitbringen. Reglement im Wesentlichen wie bei RC'05, jedoch sind auch komplexere Hindernisse (z.B. Sackgassen) möglich. &lt;br /&gt;
&lt;br /&gt;
'''Puck Collect'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter - von denen einem die Farbe rot, dem anderen blau zugeteilt wird - treten gegeneinander an. Auf dem Spielfeld sind kleine rote und blaue Scheiben (Pucks) verteilt. Ziel ist es, möglichst schnell alle Pucks der eigenen Farbe einzusammeln und zur eigenen, farblich gekennzeichneten Homebase zu bringen. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotchallenge.at/ RobotChallenge]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==SPURT==&lt;br /&gt;
Der Wettbewerb SPURT (die Abkürzung steht für &amp;quot;Schüler-Projekte um Roboter-Technik&amp;quot;) wird jährlich von der Universität Rostock veranstaltet. SPURT richtet sich an technikinteressierte Schüler. Die zu lösende Aufgabe ist eine Linienverfolgung. Wer am schnellsten die herzförmige Linie abfährt, hat gewonnen.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://spurt.uni-rostock.de/ Wettbewerb SPURT]&lt;br /&gt;
&lt;br /&gt;
==ELROB==&lt;br /&gt;
Die deutsche Bundeswehr läd Firmen und Privatpersonen ein, am European Land-Robot Trial teilzunehmen (findet 2010 zum fünften Mal statt). Die ELROB wird veranstaltet, um einen Überblick über den europäischen State-of-the-art auf dem Gebiet von UGVs (unmanned ground vehicles) mit Fokus auf kurzfristig realisierbare Robotersystemen zu liefern. Hinsichtlich der vorhandenen Fähigkeiten versuchen die Organisatoren, technische Lösungen zu fördern, die den Betrieb unbemannter Fahrzeuge (UGV) verbessern. Repräsentanten aus Militär, Grenzschutz, Spezialkräften, Polizei, Feuerwehr, und Zivilschutzagenturen aus vielen europäischen Ländern werden anwesend sein. Die ELROB wird von einer Ausstellung begleitet, welche eine breite Vielzahl an Robotikaspekten umfasst.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.elrob.org/ Homepage von ELROB]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==ROBOCOM==&lt;br /&gt;
Bei diesem Wettbewerb soll eine vorgegebene Aufgabe mit LEGO MINDSTORMS NXT Robotern autonom, d.h. ohne Eingriffe von außen bewältigt werden. Mit diesem Wettbewerb möchte die Fachhochschule Gelsenkirchen in den Schulen den Einsatz moderner Techniken fördern und Schülerinnen und Schüler für ein naturwissenschaftliches Studium interessieren.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www2.fh-gelsenkirchen.de/FH-Sites/FB1/index.php?id=791&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Derzeit nicht regelmäßig stattfindende Wettbewerbe =&lt;br /&gt;
&lt;br /&gt;
==RobotLiga==&lt;br /&gt;
Die RobotLiga fand bis 2007 in Kaiserslautern statt, neuere Termine sind nicht bekannt. Teilnehmen konnten alle interessierten Roboterbastler.&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 75cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotliga.de/ RobotLiga]&lt;br /&gt;
&lt;br /&gt;
==RoboTest==&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2 bis 3cm breit. Es starten immer zwei Roboter gleichzeitig in einem Parallelslalom. Der Wettbewerb läuft in mehreren Runden nach dem KO-System. &lt;br /&gt;
&lt;br /&gt;
'''BLOCKED LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Auf der Strecke stehen Hindernisse, die umfahren werden müssen. &lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2 bis 5cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, innerhalb von drei Minuten möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MICRO LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen für sehr kleine Roboter. Die maximale Größe liegt bei 8x8x8cm und 200g. Je kleiner und leichter der Roboter ist, desto mehr Bonuspunkte gibt es.  &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''JUST WALK'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 1m zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://WWW.ROBOTEST.DE/ RoboTest]&lt;br /&gt;
&lt;br /&gt;
==GSF Robot Contest==&lt;br /&gt;
Ein neuer Wettbewerb für Hobbyrobotiker. Er findet am 19.5.07 erstmals statt. Austragungsort ist Fröndenberg (Raum Dortmund/Unna).&lt;br /&gt;
Die Aufgaben sind teilweise angelehnt an die der RobotLiga.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegenrische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Naqch einem akustischen &amp;quot;Feueralarm&amp;quot; muss eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude gefunden und gelöscht werden. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinader an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 100cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREESTYLE'''&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Disziplin hat jeder Teilnehmer die Möglichkeit seinen Roboter vorzustellen und zu zeigen was dieser kann.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www.gsf-robot-contest.de/&lt;br /&gt;
&lt;br /&gt;
==RoboKing==&lt;br /&gt;
RoboKing ist ein Wettbewerb für technikinteressierte Schüler, der jährlich von der TU Chemnitz organisiert wird. Jedes Team besteht aus 3 bis 5 Schülern und einem erwachsenem Teamleiter. RoboKing richtet sich ausdrücklich auch an Schülergruppen ohne große Vorkenntnisse. Ziel der Initiative ist, Schüler für ein Studium ingenieurwissenschaftlicher Fächer zu begeistern und zu zeigen, dass auch Schulfächer wie Physik und Informatik eine Menge Spaß machen können. Das Durchschnittsalter der Teilnehmer liegt bei etwa 16 Jahren. Die jüngsten Teilnehmer waren 10 Jahre alt. &lt;br /&gt;
&lt;br /&gt;
Besonderes Highlight des Wettberwebs RoboKing ist zweifellos eine Gutschrift, von denen die Teilnehmer alle Materialien die zum Bau des Roboters benötigt werden, bezahlen können. Dadurch unterscheidet sich dieser Wettbewerb von allen vergleichbaren, denn auf die teilnehmenden Schüler kommen keine Kosten für Material zu. Jedes Jahr werden 25 Teams mit dieser Gutschrift finanziell unterstützt. Ab dem Wettbewerb RoboKing 2007 (startet im Frühjahr 2006) können zusätzlich auch alle Teams teilnehmen, die sich selbst finanzieren.&lt;br /&gt;
&lt;br /&gt;
Die Endrunde des Wettbewerbs wurde 2004 und auf der Hannover Messe ausgetragen. 2006 fand das Finale auf der digital living / CeBIT statt.&lt;br /&gt;
Eine weitere Besonderheit des Wettbewerbs: Jedes Jahr müssen die Teilnehmer eine andere Aufgabenstellung lösen.  Bei den vergangenen Wettbewerben mussten die Roboter sicher durch ein großes Labyrinth navigieren, Tennisbälle einsammeln und in die eigene Basis bringen oder Bauklötzchen durch einen Hindernisparcours mit Graben, Brücke und Schlucht transportieren. Die Teilnehmer haben nach Bekanntgabe der Spielregeln etwa 8 Monate Zeit, die Aufgabe zu lösen.&lt;br /&gt;
&lt;br /&gt;
RoboKing finanziert sich ausschließlich über Spenden von zahlreichen Sponsoren. Verantwortlich für die Organisation sind die Mitarbeiter und Studenten der Professur Prozessautomatisierung der TU Chemnitz.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.roboking.de www.roboking.de]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Praxis]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17400</id>
		<title>Programmer</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17400"/>
				<updated>2011-04-15T17:30:34Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Adapter 10polig &amp;lt;-&amp;gt; 6polig */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Als '''Programmer''' wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des &amp;quot;serial Download&amp;quot; eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen &amp;quot;Standard&amp;quot; [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen &amp;quot;billig&amp;quot; Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene &amp;quot;Intelligenz&amp;quot; verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.&lt;br /&gt;
&lt;br /&gt;
== Parallelport ISP Programmer ==&lt;br /&gt;
&lt;br /&gt;
=== STK 200 kompatible Programmer ===&lt;br /&gt;
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. &lt;br /&gt;
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. &lt;br /&gt;
&lt;br /&gt;
 LPT-Pinning des STK200&lt;br /&gt;
 SCK   = 6;&lt;br /&gt;
 MOSI  = 7;&lt;br /&gt;
 RESET = 9;&lt;br /&gt;
 MISO  = 10;&lt;br /&gt;
&lt;br /&gt;
=== SP12 kompatible Programmer ===&lt;br /&gt;
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. &lt;br /&gt;
 &lt;br /&gt;
 LPT-Pinning des SP12&lt;br /&gt;
 VCC   = 4,5,6,7,8;&lt;br /&gt;
 RESET = 3;&lt;br /&gt;
 SCK   = 2;&lt;br /&gt;
 MOSI  = 9;&lt;br /&gt;
 MISO  = 11;&lt;br /&gt;
&lt;br /&gt;
== Pseudo serielle Programmer (SI-Prog) ==&lt;br /&gt;
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Echte serielle Programmer ==&lt;br /&gt;
Echte serielle Programmer basieren oft entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und auch mit handelsüblichen USB-Serial-Adaptern betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das alte Protokoll nach AN910 ist problematisch bei der Unterstützung neuer Controller, denn hier muß der Programmer die ID des Controllers kennen. Für neue Controller braucht man also ein Update der Software im Programmer.  Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
== USB Programmer ==&lt;br /&gt;
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für günstige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab, AVR-Doper, siehe Weblinks).  Das USB-Protokoll ist meistens nur minimalistisch und nicht vollständig umgesetzt, wodurch es zu Inkompatibilitäten kommen kann.&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz hat die Nutzung der AVR-Controller den großen Vorteil, dass sich nun ohne SMD-Bauteile auch USB-Programmierer bauen lassen, die an modernen Laptops, ohne serielle Schnittstelle funktionieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==JTAG &amp;amp; PDI Programmer==&lt;br /&gt;
Mit veröffentlichung der '''Xmegas''' hat sich ATMEL vom ISP Standard getrennt,&lt;br /&gt;
statt dessen komt '''PDI''' oder '''JTAG''' zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Anbieter entsprechender Programmieradapter sind z.Zt. spärlich.&lt;br /&gt;
&lt;br /&gt;
Im Internet und auch hier im RN-Wissen stösst man auf der Suche nach JTAG-Programmern schnell auf eine Nachbauversion des JTAG ICE, dieser ist der vorläufer des mmt. aktuellen JTAG ICE MKII. Der JTAG ICE unterstützt nach meinen Recherchen jedoch nicht die aktuellen X-Megas.&lt;br /&gt;
&lt;br /&gt;
Auf der suche nach entsprechende Programmern bin ich, bis auf einen, auf die relativ teuerern und für Hobbyisten unerschwinglichen Programmer gestossen.&lt;br /&gt;
 JTAG ICE MKII [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3353]&lt;br /&gt;
 AVR-ONE! [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4279]   &lt;br /&gt;
 AVR-Dragon [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3891]&lt;br /&gt;
letzter unterstützt u.a. ISP, JTAG und PDI Programmierung, also alles was man benötigt. &lt;br /&gt;
&lt;br /&gt;
Der '''AVR-Dragon''' ist von den aufgeführten Geräte '''mmt. die günstigste variante''' (ca €50,-) soll allerdings etwas empfindlch sein und über keinerlei Schutzmechanismen verfügen und keinerlei Ausstattung (Kabel/Anleitung) bereit stellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ISP-Anschluss ==&lt;br /&gt;
&lt;br /&gt;
=== 10poliger ISP Anschluss ===&lt;br /&gt;
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.&lt;br /&gt;
&lt;br /&gt;
 1 - MOSI&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - LED (oft auch unbelegt)&lt;br /&gt;
 4 - GND&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
 7 - SCK&lt;br /&gt;
 8 - GND&lt;br /&gt;
 9 - MISO&lt;br /&gt;
 10 - GND&lt;br /&gt;
&lt;br /&gt;
=== 6poliger ISP Anschluss ===&lt;br /&gt;
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber teurer als die zehnpolige Variante.  &lt;br /&gt;
 1 - MISO&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - SCK&lt;br /&gt;
 4 - MOSI&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
&lt;br /&gt;
=== Adapter 10polig &amp;lt;-&amp;gt; 6polig ===&lt;br /&gt;
Ein Adapter zur Verbindung der beiden Steckerarten lässt sich einfach auf einem Stück Lochrasterplatine aufbauen.&lt;br /&gt;
Hier ein mögliches Layout, mit dem ein sehr platzsparender Aufbau möglich ist.&lt;br /&gt;
&lt;br /&gt;
Am besten baut man die Schaltung auf einer Platine mit Punktraster auf, dann muss man keine Leiterbahnen auftrennen.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass Pin 3 des zehnpoligen Steckers '''vor dem Löten entfernt wird''' (lässt sich mit einer Zange herausziehen, ggf. vorher den Pin etwas mit dem Lötkolben erwärmen). Dann kann die Masseverbindung von Pin6/sechspol zu Pin4,6,8,10/zehnpol einfach auf der Unterseite durch diese Lücke geführt werden. So ergibt sich ein besonders einfaches Layout ohne Leitungskreuzungen.&lt;br /&gt;
&lt;br /&gt;
Nun werden die Stecker eingelötet, und alle Verbindungen auf der Unterseite der Platine hergestellt. Da sich dabei keine Leitungen überkreuzen, kann unisolierter Draht verwendet werden. Um ihn stabil zu befestigen, kann man ihn noch auf die unbelegten Lötaugen entlang des Drahtes anlöten.&lt;br /&gt;
&lt;br /&gt;
Schließlich empfiehlt es sich (nach erfolgreichem Funktionstest) die Unterseite der Platine zu isolieren (z.B. mit Klebeband), damit keine Kurzschlüsse mit anderen metallischen Gegenständen auftreten können.&lt;br /&gt;
{| border=1&lt;br /&gt;
 |[[Bild:Ispadapter.jpg]]&lt;br /&gt;
 |[[Bild:Ispadapter layout.png]]&lt;br /&gt;
 |-&lt;br /&gt;
 |ISP-Adapter&lt;br /&gt;
 |Lochraster-Layout&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
== Autor ==&lt;br /&gt;
*[[Benutzer:Martin Fiedler|Martin Fiedler]]&lt;br /&gt;
*Kleinere Änderungen Frank&lt;br /&gt;
*JTAG &amp;amp; PDI Programmer [[Benutzer:Darwin.nuernberg|Darwin.nuernberg]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP&lt;br /&gt;
* [[ISP]]&lt;br /&gt;
* [[RN-Definitionen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]&lt;br /&gt;
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]&lt;br /&gt;
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.&lt;br /&gt;
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung&lt;br /&gt;
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]&lt;br /&gt;
* [http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=73&amp;amp;products_id=161 Original Bascom Programmer (USB/Keine Firmware notwendig)]&lt;br /&gt;
* [http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=73&amp;amp;products_id=201 original Atmel USB Programmer] &lt;br /&gt;
* [http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=73&amp;amp;products_id=190 Robotikhardware] - Bezugsquelle für Adapter 6 auf 10 und umgekehrt&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/AVR_In_System_Programmer Übersicht verschiedener Programmierer] (Mikrocontroller.net)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17342</id>
		<title>Programmer</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17342"/>
				<updated>2011-03-30T11:32:08Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Adapter 10polig &amp;lt;-&amp;gt; 6polig */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Als '''Programmer''' wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des &amp;quot;serial Download&amp;quot; eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen &amp;quot;Standard&amp;quot; [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen &amp;quot;billig&amp;quot; Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene &amp;quot;Intelligenz&amp;quot; verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.&lt;br /&gt;
&lt;br /&gt;
== Parallelport ISP Programmer ==&lt;br /&gt;
&lt;br /&gt;
=== STK 200 kompatible Programmer ===&lt;br /&gt;
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. &lt;br /&gt;
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. &lt;br /&gt;
&lt;br /&gt;
 LPT-Pinning des STK200&lt;br /&gt;
 SCK   = 6;&lt;br /&gt;
 MOSI  = 7;&lt;br /&gt;
 RESET = 9;&lt;br /&gt;
 MISO  = 10;&lt;br /&gt;
&lt;br /&gt;
=== SP12 kompatible Programmer ===&lt;br /&gt;
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. &lt;br /&gt;
 &lt;br /&gt;
 LPT-Pinning des SP12&lt;br /&gt;
 VCC   = 4,5,6,7,8;&lt;br /&gt;
 RESET = 3;&lt;br /&gt;
 SCK   = 2;&lt;br /&gt;
 MOSI  = 9;&lt;br /&gt;
 MISO  = 11;&lt;br /&gt;
&lt;br /&gt;
== Pseudo serielle Programmer (SI-Prog) ==&lt;br /&gt;
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Echte serielle Programmer ==&lt;br /&gt;
Echte serielle Programmer basieren oft entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und auch mit handelsüblichen USB-Serial-Adaptern betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das alte Protokoll nach AN910 ist problematisch bei der Unterstützung neuer Controller, denn hier muß der Programmer die ID des Controllers kennen. Für neue Controller braucht man also ein Update der Software im Programmer.  Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
== USB Programmer ==&lt;br /&gt;
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für günstige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab, AVR-Doper, siehe Weblinks).  Das USB-Protokoll ist meistens nur minimalistisch und nicht vollständig umgesetzt, wodurch es zu Inkompatibilitäten kommen kann.&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz hat die Nutzung der AVR-Controller den großen Vorteil, dass sich nun ohne SMD-Bauteile auch USB-Programmierer bauen lassen, die an modernen Laptops, ohne serielle Schnittstelle funktionieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==JTAG &amp;amp; PDI Programmer==&lt;br /&gt;
Mit veröffentlichung der '''Xmegas''' hat sich ATMEL vom ISP Standard getrennt,&lt;br /&gt;
statt dessen komt '''PDI''' oder '''JTAG''' zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Anbieter entsprechender Programmieradapter sind z.Zt. spärlich.&lt;br /&gt;
&lt;br /&gt;
Im Internet und auch hier im RN-Wissen stösst man auf der Suche nach JTAG-Programmern schnell auf eine Nachbauversion des JTAG ICE, dieser ist der vorläufer des mmt. aktuellen JTAG ICE MKII. Der JTAG ICE unterstützt nach meinen Recherchen jedoch nicht die aktuellen X-Megas.&lt;br /&gt;
&lt;br /&gt;
Auf der suche nach entsprechende Programmern bin ich, bis auf einen, auf die relativ teuerern und für Hobbyisten unerschwinglichen Programmer gestossen.&lt;br /&gt;
 JTAG ICE MKII [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3353]&lt;br /&gt;
 AVR-ONE! [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4279]   &lt;br /&gt;
 AVR-Dragon [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3891]&lt;br /&gt;
letzter unterstützt u.a. ISP, JTAG und PDI Programmierung, also alles was man benötigt. &lt;br /&gt;
&lt;br /&gt;
Der '''AVR-Dragon''' ist von den aufgeführten Geräte '''mmt. die günstigste variante''' (ca €50,-) soll allerdings etwas empfindlch sein und über keinerlei Schutzmechanismen verfügen und keinerlei Ausstattung (Kabel/Anleitung) bereit stellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ISP-Anschluss ==&lt;br /&gt;
&lt;br /&gt;
=== 10poliger ISP Anschluss ===&lt;br /&gt;
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.&lt;br /&gt;
&lt;br /&gt;
 1 - MOSI&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - LED (oft auch unbelegt)&lt;br /&gt;
 4 - GND&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
 7 - SCK&lt;br /&gt;
 8 - GND&lt;br /&gt;
 9 - MISO&lt;br /&gt;
 10 - GND&lt;br /&gt;
&lt;br /&gt;
=== 6poliger ISP Anschluss ===&lt;br /&gt;
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber teurer als die zehnpolige Variante.  &lt;br /&gt;
 1 - MISO&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - SCK&lt;br /&gt;
 4 - MOSI&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
&lt;br /&gt;
=== Adapter 10polig &amp;lt;-&amp;gt; 6polig ===&lt;br /&gt;
Ein Adapter zur Verbindung der beiden Steckerarten lässt sich einfach auf einem Stück Lochrasterplatine aufbauen.&lt;br /&gt;
Hier ein mögliches Layout, mit dem ein sehr platzsparender Aufbau möglich ist.&lt;br /&gt;
&lt;br /&gt;
Am besten baut man die Schaltung auf einer Platine mit Punktraster auf, dann muss man keine Leiterbahnen auftrennen.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass Pin 3 des zehnpoligen Steckers '''vor dem Löten entfernt wird''' (lässt sich mit einer Zange herausziehen, ggf. vorher den Pin etwas mit dem Lötkolben erwärmen). Dann kann die Masseverbindung von Pin6/sechspol zu Pin4,6,8,10/zehnpol einfach auf der Unterseite durch diese Lücke geführt werden.&lt;br /&gt;
&lt;br /&gt;
Nun werden die Stecker eingelötet, und alle Verbindungen auf der Unterseite der Platine hergestellt. Da sich dabei keine Leitungen überkreuzen, kann unisolierter Draht verwendet werden. Um ihn stabil zu befestigen, kann man ihn noch auf die unbelegten Lötaugen entlag des Drahtes anlöten.&lt;br /&gt;
&lt;br /&gt;
Schließlich empfiehlt es sich (nach erfolgreichem Funktionstest) die Unterseite der Platine zu isolieren (z.B. mit Klebeband), damit keine Kurzschlüsse mit anderen metallischen Gegenständen auftreten können.&lt;br /&gt;
{| border=1&lt;br /&gt;
 |[[Bild:Ispadapter.jpg]]&lt;br /&gt;
 |[[Bild:Ispadapter layout.png]]&lt;br /&gt;
 |-&lt;br /&gt;
 |ISP-Adapter&lt;br /&gt;
 |Lochraster-Layout&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
== Autor ==&lt;br /&gt;
*[[Benutzer:Martin Fiedler|Martin Fiedler]]&lt;br /&gt;
*Kleinere Änderungen Frank&lt;br /&gt;
*JTAG &amp;amp; PDI Programmer [[Benutzer:Darwin.nuernberg|Darwin.nuernberg]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP&lt;br /&gt;
* [[ISP]]&lt;br /&gt;
* [[RN-Definitionen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]&lt;br /&gt;
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]&lt;br /&gt;
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.&lt;br /&gt;
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung&lt;br /&gt;
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]&lt;br /&gt;
* [http://shop.embedit.de/browse_030001002_66__.php embedit.de] Bezugsquelle für sechspoligen Stecker&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/AVR_In_System_Programmer Übersicht verschiedener Programmierer] (Mikrocontroller.net)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17341</id>
		<title>Programmer</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17341"/>
				<updated>2011-03-30T11:28:48Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Adapter 10polig &amp;lt;-&amp;gt; 6polig */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Als '''Programmer''' wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des &amp;quot;serial Download&amp;quot; eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen &amp;quot;Standard&amp;quot; [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen &amp;quot;billig&amp;quot; Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene &amp;quot;Intelligenz&amp;quot; verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.&lt;br /&gt;
&lt;br /&gt;
== Parallelport ISP Programmer ==&lt;br /&gt;
&lt;br /&gt;
=== STK 200 kompatible Programmer ===&lt;br /&gt;
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. &lt;br /&gt;
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. &lt;br /&gt;
&lt;br /&gt;
 LPT-Pinning des STK200&lt;br /&gt;
 SCK   = 6;&lt;br /&gt;
 MOSI  = 7;&lt;br /&gt;
 RESET = 9;&lt;br /&gt;
 MISO  = 10;&lt;br /&gt;
&lt;br /&gt;
=== SP12 kompatible Programmer ===&lt;br /&gt;
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. &lt;br /&gt;
 &lt;br /&gt;
 LPT-Pinning des SP12&lt;br /&gt;
 VCC   = 4,5,6,7,8;&lt;br /&gt;
 RESET = 3;&lt;br /&gt;
 SCK   = 2;&lt;br /&gt;
 MOSI  = 9;&lt;br /&gt;
 MISO  = 11;&lt;br /&gt;
&lt;br /&gt;
== Pseudo serielle Programmer (SI-Prog) ==&lt;br /&gt;
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Echte serielle Programmer ==&lt;br /&gt;
Echte serielle Programmer basieren oft entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und auch mit handelsüblichen USB-Serial-Adaptern betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das alte Protokoll nach AN910 ist problematisch bei der Unterstützung neuer Controller, denn hier muß der Programmer die ID des Controllers kennen. Für neue Controller braucht man also ein Update der Software im Programmer.  Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
== USB Programmer ==&lt;br /&gt;
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für günstige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab, AVR-Doper, siehe Weblinks).  Das USB-Protokoll ist meistens nur minimalistisch und nicht vollständig umgesetzt, wodurch es zu Inkompatibilitäten kommen kann.&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz hat die Nutzung der AVR-Controller den großen Vorteil, dass sich nun ohne SMD-Bauteile auch USB-Programmierer bauen lassen, die an modernen Laptops, ohne serielle Schnittstelle funktionieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==JTAG &amp;amp; PDI Programmer==&lt;br /&gt;
Mit veröffentlichung der '''Xmegas''' hat sich ATMEL vom ISP Standard getrennt,&lt;br /&gt;
statt dessen komt '''PDI''' oder '''JTAG''' zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Anbieter entsprechender Programmieradapter sind z.Zt. spärlich.&lt;br /&gt;
&lt;br /&gt;
Im Internet und auch hier im RN-Wissen stösst man auf der Suche nach JTAG-Programmern schnell auf eine Nachbauversion des JTAG ICE, dieser ist der vorläufer des mmt. aktuellen JTAG ICE MKII. Der JTAG ICE unterstützt nach meinen Recherchen jedoch nicht die aktuellen X-Megas.&lt;br /&gt;
&lt;br /&gt;
Auf der suche nach entsprechende Programmern bin ich, bis auf einen, auf die relativ teuerern und für Hobbyisten unerschwinglichen Programmer gestossen.&lt;br /&gt;
 JTAG ICE MKII [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3353]&lt;br /&gt;
 AVR-ONE! [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4279]   &lt;br /&gt;
 AVR-Dragon [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3891]&lt;br /&gt;
letzter unterstützt u.a. ISP, JTAG und PDI Programmierung, also alles was man benötigt. &lt;br /&gt;
&lt;br /&gt;
Der '''AVR-Dragon''' ist von den aufgeführten Geräte '''mmt. die günstigste variante''' (ca €50,-) soll allerdings etwas empfindlch sein und über keinerlei Schutzmechanismen verfügen und keinerlei Ausstattung (Kabel/Anleitung) bereit stellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ISP-Anschluss ==&lt;br /&gt;
&lt;br /&gt;
=== 10poliger ISP Anschluss ===&lt;br /&gt;
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.&lt;br /&gt;
&lt;br /&gt;
 1 - MOSI&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - LED (oft auch unbelegt)&lt;br /&gt;
 4 - GND&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
 7 - SCK&lt;br /&gt;
 8 - GND&lt;br /&gt;
 9 - MISO&lt;br /&gt;
 10 - GND&lt;br /&gt;
&lt;br /&gt;
=== 6poliger ISP Anschluss ===&lt;br /&gt;
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber teurer als die zehnpolige Variante.  &lt;br /&gt;
 1 - MISO&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - SCK&lt;br /&gt;
 4 - MOSI&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
&lt;br /&gt;
=== Adapter 10polig &amp;lt;-&amp;gt; 6polig ===&lt;br /&gt;
Ein Adapter zur Verbindung der beiden Steckerarten lässt sich einfach auf einem Stück Lochrasterplatine aufbauen.&lt;br /&gt;
Hier ein mögliches Layout, mit dem ein sehr platzsparender Aufbau möglich ist.&lt;br /&gt;
&lt;br /&gt;
Am besten baut man die Schaltung auf einer Platine mit Punktraster auf, dann muss man keine Leiterbahnen auftrennen.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass Pin 3 des zehnpoligen Steckers '''vor dem Löten entfernt wird''' (lässt sich mit einer Zange herausziehen, ggf. vorher den Pin etwas mit dem Lötkolben erwärmen). Dann kann die Masseverbindung von Pin6/sechspol zu Pin4,6,8,10/zehnpol einfach auf der Unterseite durch diese Lücke geführt werden.&lt;br /&gt;
&lt;br /&gt;
Nun werden die Stecker eingelötet, und alle Verbindungen auf der Unterseite der Platine hergestellt. Da sich dabei keine Leitungen überkreuzen, kann unisolierter Drahrt verwendet werden. Um ihn stabil zu befestigen, kann man ihn noch auf die unbelegten Lötaugen entlag des Drahtes anlöten.&lt;br /&gt;
&lt;br /&gt;
Schließlich empfiehlt es sich (nach erfolgreichem Funktionstest) die Unterseite der Platine zu isolieren (z.B. mit Klebeband), damit keine Kurzschlüsse mit anderen metallischen Gegenständen auftreten können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Ispadapter.jpg|framed|400px|ISP-Adapter]]&lt;br /&gt;
[[Bild:Ispadapter layout.png|framed|400px|Lochraster-Layout]]&lt;br /&gt;
&lt;br /&gt;
== Autor ==&lt;br /&gt;
*[[Benutzer:Martin Fiedler|Martin Fiedler]]&lt;br /&gt;
*Kleinere Änderungen Frank&lt;br /&gt;
*JTAG &amp;amp; PDI Programmer [[Benutzer:Darwin.nuernberg|Darwin.nuernberg]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP&lt;br /&gt;
* [[ISP]]&lt;br /&gt;
* [[RN-Definitionen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]&lt;br /&gt;
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]&lt;br /&gt;
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.&lt;br /&gt;
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung&lt;br /&gt;
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]&lt;br /&gt;
* [http://shop.embedit.de/browse_030001002_66__.php embedit.de] Bezugsquelle für sechspoligen Stecker&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/AVR_In_System_Programmer Übersicht verschiedener Programmierer] (Mikrocontroller.net)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17340</id>
		<title>Programmer</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=17340"/>
				<updated>2011-03-30T11:26:23Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* ISP-Anschluss */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Als '''Programmer''' wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des &amp;quot;serial Download&amp;quot; eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen &amp;quot;Standard&amp;quot; [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen &amp;quot;billig&amp;quot; Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene &amp;quot;Intelligenz&amp;quot; verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.&lt;br /&gt;
&lt;br /&gt;
== Parallelport ISP Programmer ==&lt;br /&gt;
&lt;br /&gt;
=== STK 200 kompatible Programmer ===&lt;br /&gt;
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. &lt;br /&gt;
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. &lt;br /&gt;
&lt;br /&gt;
 LPT-Pinning des STK200&lt;br /&gt;
 SCK   = 6;&lt;br /&gt;
 MOSI  = 7;&lt;br /&gt;
 RESET = 9;&lt;br /&gt;
 MISO  = 10;&lt;br /&gt;
&lt;br /&gt;
=== SP12 kompatible Programmer ===&lt;br /&gt;
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. &lt;br /&gt;
 &lt;br /&gt;
 LPT-Pinning des SP12&lt;br /&gt;
 VCC   = 4,5,6,7,8;&lt;br /&gt;
 RESET = 3;&lt;br /&gt;
 SCK   = 2;&lt;br /&gt;
 MOSI  = 9;&lt;br /&gt;
 MISO  = 11;&lt;br /&gt;
&lt;br /&gt;
== Pseudo serielle Programmer (SI-Prog) ==&lt;br /&gt;
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Echte serielle Programmer ==&lt;br /&gt;
Echte serielle Programmer basieren oft entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und auch mit handelsüblichen USB-Serial-Adaptern betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das alte Protokoll nach AN910 ist problematisch bei der Unterstützung neuer Controller, denn hier muß der Programmer die ID des Controllers kennen. Für neue Controller braucht man also ein Update der Software im Programmer.  Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
== USB Programmer ==&lt;br /&gt;
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für günstige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab, AVR-Doper, siehe Weblinks).  Das USB-Protokoll ist meistens nur minimalistisch und nicht vollständig umgesetzt, wodurch es zu Inkompatibilitäten kommen kann.&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz hat die Nutzung der AVR-Controller den großen Vorteil, dass sich nun ohne SMD-Bauteile auch USB-Programmierer bauen lassen, die an modernen Laptops, ohne serielle Schnittstelle funktionieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==JTAG &amp;amp; PDI Programmer==&lt;br /&gt;
Mit veröffentlichung der '''Xmegas''' hat sich ATMEL vom ISP Standard getrennt,&lt;br /&gt;
statt dessen komt '''PDI''' oder '''JTAG''' zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Anbieter entsprechender Programmieradapter sind z.Zt. spärlich.&lt;br /&gt;
&lt;br /&gt;
Im Internet und auch hier im RN-Wissen stösst man auf der Suche nach JTAG-Programmern schnell auf eine Nachbauversion des JTAG ICE, dieser ist der vorläufer des mmt. aktuellen JTAG ICE MKII. Der JTAG ICE unterstützt nach meinen Recherchen jedoch nicht die aktuellen X-Megas.&lt;br /&gt;
&lt;br /&gt;
Auf der suche nach entsprechende Programmern bin ich, bis auf einen, auf die relativ teuerern und für Hobbyisten unerschwinglichen Programmer gestossen.&lt;br /&gt;
 JTAG ICE MKII [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3353]&lt;br /&gt;
 AVR-ONE! [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4279]   &lt;br /&gt;
 AVR-Dragon [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3891]&lt;br /&gt;
letzter unterstützt u.a. ISP, JTAG und PDI Programmierung, also alles was man benötigt. &lt;br /&gt;
&lt;br /&gt;
Der '''AVR-Dragon''' ist von den aufgeführten Geräte '''mmt. die günstigste variante''' (ca €50,-) soll allerdings etwas empfindlch sein und über keinerlei Schutzmechanismen verfügen und keinerlei Ausstattung (Kabel/Anleitung) bereit stellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ISP-Anschluss ==&lt;br /&gt;
&lt;br /&gt;
=== 10poliger ISP Anschluss ===&lt;br /&gt;
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.&lt;br /&gt;
&lt;br /&gt;
 1 - MOSI&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - LED (oft auch unbelegt)&lt;br /&gt;
 4 - GND&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
 7 - SCK&lt;br /&gt;
 8 - GND&lt;br /&gt;
 9 - MISO&lt;br /&gt;
 10 - GND&lt;br /&gt;
&lt;br /&gt;
=== 6poliger ISP Anschluss ===&lt;br /&gt;
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber teurer als die zehnpolige Variante.  &lt;br /&gt;
 1 - MISO&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - SCK&lt;br /&gt;
 4 - MOSI&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
&lt;br /&gt;
=== Adapter 10polig &amp;lt;-&amp;gt; 6polig ===&lt;br /&gt;
Ein Adapter zur Verbindung der beiden Steckerarten lässt sich einfach auf einem Stück Lochrasterplatine aufbauen.&lt;br /&gt;
Hier ein mögliches Layout, mit dem ein sehr platzsparender Aufbau möglich ist.&lt;br /&gt;
&lt;br /&gt;
Am besten baut man die Schaltung auf einer Platine mit Punktraster auf, dann muss man keine Leiterbahnen auftrennen.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass Pin 3 des zehnpoligen Steckers '''vor dem Löten entfernt wird''' (lässt sich mit einer Zange herausziehen, ggf. vorher den Pin etwas mit dem Lötkolben erwärmen). Dann kann die Masseverbindung von Pin6/sechspol zu Pin4,6,8,10/zehnpol einfach auf der Unterseite durch diese Lücke geführt werden.&lt;br /&gt;
&lt;br /&gt;
Nun werden die Stecker eingelötet, und alle Verbindungen auf der Unterseite der Platine hergestellt. Da sich dabei keine Leitungen überkreuzen, kann unisolierter Drahrt verwendet werden. Um ihn stabil zu befestigen, kann man ihn noch auf die unbelegten Lötaugen entlag des Drahtes anlöten.&lt;br /&gt;
&lt;br /&gt;
Schließlich empfiehlt es sich (nach erfolgreichem Funktionstest) die Unterseite der Platine zu isolieren (z.B. mit Klebeband), damit keine Kurzschlüsse mit anderen metallischen Gegenständen auftreten können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Ispadapter.jpg|thumb|400px|ISP-Adapter]]&lt;br /&gt;
[[Bild:Ispadapter layout.png|thumb|400px|Lochraster-Layout]]&lt;br /&gt;
&lt;br /&gt;
== Autor ==&lt;br /&gt;
*[[Benutzer:Martin Fiedler|Martin Fiedler]]&lt;br /&gt;
*Kleinere Änderungen Frank&lt;br /&gt;
*JTAG &amp;amp; PDI Programmer [[Benutzer:Darwin.nuernberg|Darwin.nuernberg]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP&lt;br /&gt;
* [[ISP]]&lt;br /&gt;
* [[RN-Definitionen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]&lt;br /&gt;
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]&lt;br /&gt;
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.&lt;br /&gt;
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung&lt;br /&gt;
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]&lt;br /&gt;
* [http://shop.embedit.de/browse_030001002_66__.php embedit.de] Bezugsquelle für sechspoligen Stecker&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/AVR_In_System_Programmer Übersicht verschiedener Programmierer] (Mikrocontroller.net)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Ispadapter_layout.png&amp;diff=17339</id>
		<title>Datei:Ispadapter layout.png</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Ispadapter_layout.png&amp;diff=17339"/>
				<updated>2011-03-30T11:14:13Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: Lochraster-Layout für ISP-Adapter sechspolig auf zehnpolig&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lochraster-Layout für ISP-Adapter sechspolig auf zehnpolig&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Ispadapter.jpg&amp;diff=17338</id>
		<title>Datei:Ispadapter.jpg</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Ispadapter.jpg&amp;diff=17338"/>
				<updated>2011-03-30T11:00:14Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: Adapter für AVR-ISP-Stecker sechspolig auf zehnpolig. Aufgebaut auf einem Stück Lochrasterplatine.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Adapter für AVR-ISP-Stecker sechspolig auf zehnpolig. Aufgebaut auf einem Stück Lochrasterplatine.&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Rc5&amp;diff=17333</id>
		<title>Rc5</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Rc5&amp;diff=17333"/>
				<updated>2011-03-28T21:19:12Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: durch Weiterleitung ersetzt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[RC5-Code]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Abblockkondensator&amp;diff=17332</id>
		<title>Abblockkondensator</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Abblockkondensator&amp;diff=17332"/>
				<updated>2011-03-28T21:10:06Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Viele Anfänger in Sachen Elektronik bekommen, wenn sie eine selbst entworfene Schaltung im Forum posten, als erstes zu hören: &amp;quot;Alle ICs mit Kondensatoren an den Stromversorgungspins versehen!!!&amp;quot;. Die Erklärungen, die dazu geliefert werden, schwanken zwischen &amp;lt;nicht vorhanden&amp;gt;, und langen, ausführlichen, physikalisch korrekten, aber für Laien kaum verständlichen Ausführungen. &lt;br /&gt;
Dieser Artikel soll nun dazu dienen, die Wirkung eines Abblockkondensators zu beschreiben und zu erklären, sodass in Zukunft vom Forum einfach hierhin verlinkt werden kann, wenn das Thema mal wieder zur Sprache kommt...&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Theorie ==&lt;br /&gt;
&lt;br /&gt;
Erklärung in wenigen Sätzen: Digitale ICs ziehen impulsweise sehr hohe Ströme, sodass die Spannung einbrechen kann. Das kann sich störend auf andere Teile der Schaltung auswirken. Ein Kondensator kann Energie speichern und sie sehr schnell wieder abgeben, wenn plötzlich viel Strom benötigt wird. Dadurch wird die Spannung im Rest der Schaltung stabiler gehalten. Aber jetzt Schluss mit der Theorie, die folgenden Bilder sprechen für sich (alle Aufnahmen mit Zeitbasis 0,5µs/Div):   &lt;br /&gt;
&lt;br /&gt;
[[Bild:Abblockkondensator OhneC amAVR.jpg]]&lt;br /&gt;
&lt;br /&gt;
So sieht es auf der 5V-Versorgungsleitung aus, wenn ein AVR (90S8515, 4MHz) ohne Abblockkondensatoren betrieben wird. Die periodische hohe Stromaufnahme führt zu kurzen Spannungseinbrüchen und -spitzen, die bis zu 0,25V erreichen können. &lt;br /&gt;
Diese Störungen breiten sich über die Leitungen in die gesamte Schaltung aus, und selbst 30cm Kabellänge entfernt sieht es noch so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Abblockkondensator OhneC weit entfernt.jpg]]&lt;br /&gt;
&lt;br /&gt;
Die Störungen werden schwächer, sind aber immer noch recht deutlich zu erkennen und können andere Bauteile stören.&lt;br /&gt;
&lt;br /&gt;
Abhilfe schafft nun ein Abblockkondensator, der möglichst nahe am Stromversorgungspin des AVRs gegen Masse geschaltet wird. Ein Folien-oder Keramikkondensator mit 100nF schafft Ruhe auf der Leitung:&lt;br /&gt;
 &lt;br /&gt;
[[Bild:Abblockkondensator 100nF amAVR.jpg]]&lt;br /&gt;
&lt;br /&gt;
Das übrig bleibende &amp;quot;Grundrauschen&amp;quot; ist nun so gering, dass es sich in den allermeisten Fällen nicht mehr störend auswirkt.&lt;br /&gt;
&lt;br /&gt;
Die Störungen auf der Versorgungsspannung stören nicht nur die zuverlässige Funktion der Schaltung selbst, sondern sind auch eine Quelle von Funkstörungen. Die Abblockkondensatoren sind also auch aus EMV-Gründen notwendig.&lt;br /&gt;
&lt;br /&gt;
== Praxis==&lt;br /&gt;
=== Welchen Kondensatortyp verwenden? ===&lt;br /&gt;
Als Abblockkondensator werden üblicherweise keramische Kondensatoren verwendet. Geschichtete (flache, nicht gewickelte) Folienkondensatoren sind ebenfalls geeignet, allerdings normalerweise teurer. Elkos sind ungeeignet! Sie sind meist gewickelt, und haben deswegen auch einen induktiven Anteil, verhalten sich also auch ein wenig wie eine Spule, und können daher ihre Ladung nur langsam (im Verhältnis zu Keramik oder Folie) aufnehmen oder abgeben. Daher können sie die Stromspitzen digitaler ICs nicht so effektiv abfangen. Es treten also größere Störungen auf.&lt;br /&gt;
&lt;br /&gt;
=== Welche Kapazität? ===&lt;br /&gt;
Die nötige Kapazität ist von der Schaltfrequenz des ICs abhängig. Im für Mikrocontroller wie AVRs oder PICs üblichen Frequenzbereich bis etwa 20MHz ist der genaue Wert allerdings recht unkritisch, und man kann gewöhnlicherweise einen Standardwert von 100nF verwenden. &lt;br /&gt;
Bei größeren Frequenzen sollte man sich aber etwas eingehender mit der Thematik befassen und die optimale Größe bestimmen.&lt;br /&gt;
&amp;quot;Viel hilft viel&amp;quot; gilt hier übrigens nicht! Ein sehr großer Kondensator hat unter Umständen einen größeren Innenwiderstand als ein kleinerer, und damit evtl. sogar eine geringere Wirkung.&lt;br /&gt;
&lt;br /&gt;
=== Wo montieren? ===&lt;br /&gt;
Damit der Kondensator seine Wirkung optimal entfalten kann, sollte er so nahem wie möglich am IC platziert werden. Bei vielen ICs sind die Versorgungsanschlüssen VCC und GND direkt nebeneinander angeordnet. Hier kann man dann den Kondensator sehr einfach parallel neben dem IC einlöten. &lt;br /&gt;
Manche ICs haben mehrere Anschlüsse für VCC/GND. Hier sollte man möglichst an jedem dieser Anschlüsse eine eigenen Kondensator setzen, wenn diese auf entgegengesetzten Seiten des ICs liegen.&lt;br /&gt;
&lt;br /&gt;
== Weiterführende Weblinks ==&lt;br /&gt;
* [http://www.cypress.com/?docID=24577 Cypress AN1032: Using Decoupling Capacitors]&lt;br /&gt;
&lt;br /&gt;
[[Category:Praxis]]&lt;br /&gt;
[[Category:Elektronik]]&lt;br /&gt;
[[Category:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Diskussion:TWI_Slave_mit_avr-gcc&amp;diff=16764</id>
		<title>Diskussion:TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Diskussion:TWI_Slave_mit_avr-gcc&amp;diff=16764"/>
				<updated>2010-07-02T14:39:19Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Kelinigkeiten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hallo Uwe,&lt;br /&gt;
&lt;br /&gt;
als mein Master mit Deinem Slave reden wollte, hängte sich der wegen nen Programmierfehler meines Masters auf. Die SCL-Leitung hat er dadurch einfach nicht mehr losgelassen. Durch ändern der Zeile&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC); &lt;br /&gt;
&lt;br /&gt;
nach &lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC); &lt;br /&gt;
&lt;br /&gt;
war alles in Butter.&lt;br /&gt;
&lt;br /&gt;
Gruß Frank&lt;br /&gt;
&lt;br /&gt;
:: Ok, habe es jetzt korrigiert, aber noch nicht selbst getestet... Solle laut Datenblatt aber korrekt sein. mfg --[[Benutzer:Uwegw|uwegw]] 11:47, 12. Apr 2010 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Kelinigkeiten ==&lt;br /&gt;
&lt;br /&gt;
Hallo,&lt;br /&gt;
&lt;br /&gt;
ich habe den Code für ein Projekt vor 2 Jahren benutzt, jetzt habe ich nach dem Code gesucht um ein Update zu machen.&lt;br /&gt;
&lt;br /&gt;
Die Oben genannten Probleme hatte ich damals auch - jetzt beim ersetzen des Moduls fällt mir folgendes auf:&lt;br /&gt;
&lt;br /&gt;
- I2C_reg_Schreibschutz ist nicht definiert und kommt im Code auch nur einmal vor. Ich denke mal, dass es dafür sorgen soll, dass richtig adressiert worden ist, oder?&lt;br /&gt;
&lt;br /&gt;
I2C_reg_Schreibschutz in twislave.h definieren ich denke das war als array gedacht?&lt;br /&gt;
I2C_reg_Schreibschutz sollte in der ini routine initialisiert werden... - dabei kann man gleich den Speicherbereich vorbeschreiben.&lt;br /&gt;
: Das war tatsächlich als Array gedacht, über das man den Schreibzugriff auf bestimmte Register sperren konnte. Wenn ich es mir recht überlege, ist diese Funktion recht überflüssig. Ich habe sie also erst mal entfernt. --[[Benutzer:Uwegw|uwegw]] 16:39, 2. Jul 2010 (CEST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ich würde auch die Interrupt aktivierung nicht in der Ini routine machen, sondern lieber ausserhalb, denn normalerweise müssen ja noch andere Sachen vorbereitet werden.&lt;br /&gt;
&lt;br /&gt;
Mein Vorschlag für die Ini routine:&lt;br /&gt;
&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{   &lt;br /&gt;
    uint8_t i=0;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
    TWAR= adr; //Adresse setzen&lt;br /&gt;
    TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
    TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE);&lt;br /&gt;
    buffer_adr=0xFF;&lt;br /&gt;
    for(i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=0;&lt;br /&gt;
		I2C_reg_Schreibschutz[i]=0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Warum definierst Du i2cdata zweimal? Einmal im header reicht ....&lt;br /&gt;
&lt;br /&gt;
Ansonsten vielen Dank, das ist sehr hilfreich...&lt;br /&gt;
&lt;br /&gt;
Christian&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16763</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16763"/>
				<updated>2010-07-02T14:34:32Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: Reste des Schreibschutzes entfernt, #include &amp;lt;stdlib.h&amp;gt;  hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master. &lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen. Die Ansteuerung läuft wie bei den bekannten I2C-EEPROMs. Der Master schreibt erst die Adresse, die er lesen bzw- schreiben will. Bei einem Schreibzugriff überträgt er nun die Daten. Bei einem Lesezugriff wird ein repeated start im Lesemodus durchgeführt, dann können die Daten byteweise eingelesen werden. Die Adressen werden dabei automatisch weitergezählt, sodass mehrere Bytes in Folge verarbeitet werden können.&lt;br /&gt;
&lt;br /&gt;
Getestet wurde der Code für zwei Mega32 mit dem AVR Studio. Beachte: im AVR-Studio ist default ein ATmega128 eingestellt, unter Projekt -&amp;gt; Configuration Options kann das Device geändert werden, außerdem ist die Taktfrequenz des Controllers einzustellen. Im Projekt wird für den Master die Dateien twimaster.c und i2cmaster.h hinzugefügt, und für den Slave die twislave.c und twislave.h. &lt;br /&gt;
Wenn stattdessen ein makefile verwendet wird, müssen dort unter SRC die c-Dateien eingetragen werden.&lt;br /&gt;
&lt;br /&gt;
Die Verbindung zwischen Master und Slave erfolgt über die Pins SCL und SDA, außerdem muss ein gemeinsamer GND vorhanden sein. Abschlusswiderstände (4,7kOhm) nicht vergessen, am besten beim Master, siehe auch I2C-Definitionen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Testprogramm für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden drei Bytes erst in den Slave geschrieben, und anschließend wieder ausgelesen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// I2C-Master-Routinen von Peter Fleury verwenden &lt;br /&gt;
// siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs&lt;br /&gt;
// Hier sind auch die Dateien: i2cmaster.h und twimaster.c zu finden, die benötigt werden&lt;br /&gt;
// Letztes Update des Codes 5. April 2010 durch HannoHupmann&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot;  &lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
&lt;br /&gt;
uint8_t byte1 = 42;&lt;br /&gt;
uint8_t byte2 = 43;&lt;br /&gt;
uint8_t byte3 = 44;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  i2c_init();         // init I2C interface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00);  // Buffer Startadresse setzen 	&lt;br /&gt;
  i2c_write(byte1); // Drei Bytes schreiben...&lt;br /&gt;
  i2c_write(byte2); &lt;br /&gt;
  i2c_write(byte3); &lt;br /&gt;
  i2c_stop();       // Zugriff beenden&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
  i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
  byte1= i2c_readAck(); // Bytes lesen...&lt;br /&gt;
  byte2= i2c_readAck();&lt;br /&gt;
  byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK&lt;br /&gt;
  i2c_stop();           // Zugriff beenden&lt;br /&gt;
} &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ((byte1 != 42)||(byte2 != 43)||(byte3 != 44))&lt;br /&gt;
{&lt;br /&gt;
  /* Die Bytes wurden nicht korrekt übertragen und wieder gelesen! */ &lt;br /&gt;
}&lt;br /&gt;
    for(;;);	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Code wurde von HannoHupmann auf einem Mega32 getestet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slave == &lt;br /&gt;
Hier soll nun der Code behandelt werden der für den Slave-Controller notwendig ist. Der vorgestellte Code schreibt die Register des Slaves an die Serielle Schnittstelle, mit einem Terminal Programm kann man sich die Ausgabe ansehen und überprüfen ob alles korrekt funktioniert. &lt;br /&gt;
Der Code ist wieder an den von Peter Fleury angelehnt.&lt;br /&gt;
&lt;br /&gt;
Der Slave sollte ohne Master folgende Ausgabe liefern: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
10&lt;br /&gt;
11&lt;br /&gt;
12&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
Die Register werden der Reihe nach mit ihrem Wert angezeigt. Wird der Master hinzugefügt sollte nun folgende Ausgabe im Terminal erscheinen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
42&lt;br /&gt;
43&lt;br /&gt;
44&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. Es verwendet zur Ausgabe die UART-lib von P. Fleury, die auf derselben Homepage wie die TWI-Master-Lib zu finden ist.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für den Slave &lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
Nun kann man dort sehen, wenn der Master einen Wert ändert&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 	    //definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;           //UART-Lib von P- Fleury&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;         //nötig für Zahlumwandlung mit itoa&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Hilfsfunktion, um Zahlen über das UART auszugeben&lt;br /&gt;
void uart_puti( const int val )&lt;br /&gt;
{&lt;br /&gt;
    char buffer[8];&lt;br /&gt;
    uart_puts( itoa(val, buffer, 10) );&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
_delay_ms(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 12.4.2010 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;         //definiert den Datentyp uint8_t       &lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switch to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
						i2cdata[buffer_adr]=data; //Daten in Buffer schreibe	&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 10// I2C_REG_ANZAHL 254 Hier kann eingestellt werden wieviele Register ausgegeben werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Diskussion:TWI_Slave_mit_avr-gcc&amp;diff=16371</id>
		<title>Diskussion:TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Diskussion:TWI_Slave_mit_avr-gcc&amp;diff=16371"/>
				<updated>2010-04-12T09:47:59Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hallo Uwe,&lt;br /&gt;
&lt;br /&gt;
als mein Master mit Deinem Slave reden wollte, hängte sich der wegen nen Programmierfehler meines Masters auf. Die SCL-Leitung hat er dadurch einfach nicht mehr losgelassen. Durch ändern der Zeile&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC); &lt;br /&gt;
&lt;br /&gt;
nach &lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC); &lt;br /&gt;
&lt;br /&gt;
war alles in Butter.&lt;br /&gt;
&lt;br /&gt;
Gruß Frank&lt;br /&gt;
&lt;br /&gt;
:: Ok, habe es jetzt korrigiert, aber noch nicht selbst getestet... Solle laut Datenblatt aber korrekt sein. mfg --[[Benutzer:Uwegw|uwegw]] 11:47, 12. Apr 2010 (CEST)&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16370</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16370"/>
				<updated>2010-04-12T09:45:26Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Slave sourcecode */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master. &lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen. Die Ansteuerung läuft wie bei den bekannten I2C-EEPROMs. Der Master schreibt erst die Adresse, die er lesen bzw- schreiben will. Bei einem Schreibzugriff überträgt er nun die Daten. Bei einem Lesezugriff wird ein repeated start im Lesemodus durchgeführt, dann können die Daten byteweise eingelesen werden. Die Adressen werden dabei automatisch weitergezählt, sodass mehrere Bytes in Folge verarbeitet werden können.&lt;br /&gt;
&lt;br /&gt;
Getestet wurde der Code für zwei Mega32 mit dem AVR Studio. Beachte: im AVR-Studio ist default ein ATmega128 eingestellt, unter Projekt -&amp;gt; Configuration Options kann das Device geändert werden, außerdem ist die Taktfrequenz des Controllers einzustellen. Im Projekt wird für den Master die Dateien twimaster.c und i2cmaster.h hinzugefügt, und für den Slave die twislave.c und twislave.h. &lt;br /&gt;
Wenn stattdessen ein makefile verwendet wird, müssen dort unter SRC die c-Dateien eingetragen werden.&lt;br /&gt;
&lt;br /&gt;
Die Verbindung zwischen Master und Slave erfolgt über die Pins SCL und SDA, außerdem muss ein gemeinsamer GND vorhanden sein. Abschlusswiderstände (4,7kOhm) nicht vergessen, am besten beim Master, siehe auch I2C-Definitionen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Testprogramm für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden drei Bytes erst in den Slave geschrieben, und anschließend wieder ausgelesen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// I2C-Master-Routinen von Peter Fleury verwenden &lt;br /&gt;
// siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs&lt;br /&gt;
// Hier sind auch die Dateien: i2cmaster.h und twimaster.c zu finden, die benötigt werden&lt;br /&gt;
// Letztes Update des Codes 5. April 2010 durch HannoHupmann&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot;  &lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
&lt;br /&gt;
uint8_t byte1 = 42;&lt;br /&gt;
uint8_t byte2 = 43;&lt;br /&gt;
uint8_t byte3 = 44;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  i2c_init();         // init I2C interface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00);  // Buffer Startadresse setzen 	&lt;br /&gt;
  i2c_write(byte1); // Drei Bytes schreiben...&lt;br /&gt;
  i2c_write(byte2); &lt;br /&gt;
  i2c_write(byte3); &lt;br /&gt;
  i2c_stop();       // Zugriff beenden&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
  i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
  byte1= i2c_readAck(); // Bytes lesen...&lt;br /&gt;
  byte2= i2c_readAck();&lt;br /&gt;
  byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK&lt;br /&gt;
  i2c_stop();           // Zugriff beenden&lt;br /&gt;
} &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ((byte1 != 42)||(byte2 != 43)||(byte3 != 44))&lt;br /&gt;
{&lt;br /&gt;
  /* Die Bytes wurden nicht korrekt übertragen und wieder gelesen! */ &lt;br /&gt;
}&lt;br /&gt;
    for(;;);	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Code wurde von HannoHupmann auf einem Mega32 getestet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slave == &lt;br /&gt;
Hier soll nun der Code behandelt werden der für den Slave-Controller notwendig ist. Der vorgestellte Code schreibt die Register des Slaves an die Serielle Schnittstelle, mit einem Terminal Programm kann man sich die Ausgabe ansehen und überprüfen ob alles korrekt funktioniert. &lt;br /&gt;
Der Code ist wieder an den von Peter Fleury angelehnt.&lt;br /&gt;
&lt;br /&gt;
Der Slave sollte ohne Master folgende Ausgabe liefern: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
10&lt;br /&gt;
11&lt;br /&gt;
12&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
Die Register werden der Reihe nach mit ihrem Wert angezeigt. Wird der Master hinzugefügt sollte nun folgende Ausgabe im Terminal erscheinen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
42&lt;br /&gt;
43&lt;br /&gt;
44&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. Es verwendet zur Ausgabe die UART-lib von P. Fleury, die auf derselben Homepage wie die TWI-Master-Lib zu finden ist.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für den Slave &lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
Nun kann man dort sehen, wenn der Master einen Wert ändert&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 	    //definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;           //UART-Lib von P- Fleury&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Hilfsfunktion, um Zahlen über das UART auszugeben&lt;br /&gt;
void uart_puti( const int val )&lt;br /&gt;
{&lt;br /&gt;
    char buffer[8];&lt;br /&gt;
    uart_puts( itoa(val, buffer, 10) );&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
_delay_ms(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 12.4.2010 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;         //definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switch to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 10// I2C_REG_ANZAHL 254 Hier kann eingestellt werden wieviele Register ausgegeben werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16191</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16191"/>
				<updated>2010-04-05T17:55:22Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Slave Testprogramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master. &lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen. Die Ansteuerung läuft wie bei den bekannten I2C-EEPROMs. Der Master schreibt erst die Adresse, die er lesen bzw- schreiben will. Bei einem Schreibzugriff überträgt er nun die Daten. Bei einem Lesezugriff wird ein repeated start im Lesemodus durchgeführt, dann können die Daten byteweise eingelesen werden. Die Adressen werden dabei automatisch weitergezählt, sodass mehrere Bytes in Folge verarbeitet werden können.&lt;br /&gt;
&lt;br /&gt;
Getestet wurde der Code für zwei Mega32 mit dem AVR Studio. Beachte: im AVR-Studio ist default ein ATmega128 eingestellt, unter Projekt -&amp;gt; Configuration Options kann das Device geändert werden, außerdem ist die Taktfrequenz des Controllers einzustellen. Im Projekt wird für den Master die Dateien twimaster.c und i2cmaster.h hinzugefügt, und für den Slave die twislave.c und twislave.h. &lt;br /&gt;
Wenn stattdessen ein makefile verwendet wird, müssen dort unter SRC die c-Dateien eingetragen werden.&lt;br /&gt;
&lt;br /&gt;
Die Verbindung zwischen Master und Slave erfolgt über die Pins SCL und SDA, außerdem muss ein gemeinsamer GND vorhanden sein. Abschlusswiderstände (4,7kOhm) nicht vergessen, am besten beim Master, siehe auch I2C-Definitionen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Testprogramm für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden drei Bytes erst in den Slave geschrieben, und anschließend wieder ausgelesen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// I2C-Master-Routinen von Peter Fleury verwenden &lt;br /&gt;
// siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs&lt;br /&gt;
// Hier sind auch die Dateien: i2cmaster.h und twimaster.c zu finden, die benötigt werden&lt;br /&gt;
// Letztes Update des Codes 5. April 2010 durch HannoHupmann&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot;  &lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
&lt;br /&gt;
uint8_t byte1 = 42;&lt;br /&gt;
uint8_t byte2 = 43;&lt;br /&gt;
uint8_t byte3 = 44;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  i2c_init();         // init I2C interface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00);  // Buffer Startadresse setzen 	&lt;br /&gt;
  i2c_write(byte1); // Drei Bytes schreiben...&lt;br /&gt;
  i2c_write(byte2); &lt;br /&gt;
  i2c_write(byte3); &lt;br /&gt;
  i2c_stop();       // Zugriff beenden&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
  i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
  byte1= i2c_readAck(); // Bytes lesen...&lt;br /&gt;
  byte2= i2c_readAck();&lt;br /&gt;
  byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK&lt;br /&gt;
  i2c_stop();           // Zugriff beenden&lt;br /&gt;
} &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ((byte1 != 42)||(byte2 != 43)||(byte3 != 44))&lt;br /&gt;
{&lt;br /&gt;
  /* Die Bytes wurden nicht korrekt übertragen und wieder gelesen! */ &lt;br /&gt;
}&lt;br /&gt;
    for(;;);	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Code wurde von HannoHupmann auf einem Mega32 getestet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slave == &lt;br /&gt;
Hier soll nun der Code behandelt werden der für den Slave-Controller notwendig ist. Der vorgestellte Code schreibt die Register des Slaves an die Serielle Schnittstelle, mit einem Terminal Programm kann man sich die Ausgabe ansehen und überprüfen ob alles korrekt funktioniert. &lt;br /&gt;
Der Code ist wieder an den von Peter Fleury angelehnt.&lt;br /&gt;
&lt;br /&gt;
Der Slave sollte ohne Master folgende Ausgabe liefern: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
10&lt;br /&gt;
11&lt;br /&gt;
12&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
Die Register werden der Reihe nach mit ihrem Wert angezeigt. Wird der Master hinzugefügt sollte nun folgende Ausgabe im Terminal erscheinen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
42&lt;br /&gt;
43&lt;br /&gt;
44&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. Es verwendet zur Ausgabe die UART-lib von P. Fleury, die auf derselben Homepage wie die TWI-Master-Lib zu finden ist.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für den Slave &lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
Nun kann man dort sehen, wenn der Master einen Wert ändert&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 	    //definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;           //UART-Lib von P- Fleury&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Hilfsfunktion, um Zahlen über das UART auszugeben&lt;br /&gt;
void uart_puti( const int val )&lt;br /&gt;
{&lt;br /&gt;
    char buffer[8];&lt;br /&gt;
    uart_puts( itoa(val, buffer, 10) );&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
_delay_ms(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 5.4.2010 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;         //definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
//Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht!&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 10// I2C_REG_ANZAHL 254 Hier kann eingestellt werden wieviele Register ausgegeben werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16187</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16187"/>
				<updated>2010-04-05T17:46:21Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master. &lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen. Die Ansteuerung läuft wie bei den bekannten I2C-EEPROMs. Der Master schreibt erst die Adresse, die er lesen bzw- schreiben will. Bei einem Schreibzugriff überträgt er nun die Daten. Bei einem Lesezugriff wird ein repeated start im Lesemodus durchgeführt, dann können die Daten byteweise eingelesen werden. Die Adressen werden dabei automatisch weitergezählt, sodass mehrere Bytes in Folge verarbeitet werden können.&lt;br /&gt;
&lt;br /&gt;
Getestet wurde der Code für zwei Mega32 mit dem AVR Studio. Beachte: im AVR-Studio ist default ein ATmega128 eingestellt, unter Projekt -&amp;gt; Configuration Options kann das Device geändert werden, außerdem ist die Taktfrequenz des Controllers einzustellen. Im Projekt wird für den Master die Dateien twimaster.c und i2cmaster.h hinzugefügt, und für den Slave die twislave.c und twislave.h. &lt;br /&gt;
Wenn stattdessen ein makefile verwendet wird, müssen dort unter SRC die c-Dateien eingetragen werden.&lt;br /&gt;
&lt;br /&gt;
Die Verbindung zwischen Master und Slave erfolgt über die Pins SCL und SDA, außerdem muss ein gemeinsamer GND vorhanden sein. Abschlusswiderstände (4,7kOhm) nicht vergessen, am besten beim Master, siehe auch I2C-Definitionen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Testprogramm für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden drei Bytes erst in den Slave geschrieben, und anschließend wieder ausgelesen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// I2C-Master-Routinen von Peter Fleury verwenden &lt;br /&gt;
// siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs&lt;br /&gt;
// Hier sind auch die Dateien: i2cmaster.h und twimaster.c zu finden, die benötigt werden&lt;br /&gt;
// Letztes Update des Codes 5. April 2010 durch HannoHupmann&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot;  &lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
&lt;br /&gt;
uint8_t byte1 = 42;&lt;br /&gt;
uint8_t byte2 = 43;&lt;br /&gt;
uint8_t byte3 = 44;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  i2c_init();         // init I2C interface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00);  // Buffer Startadresse setzen 	&lt;br /&gt;
  i2c_write(byte1); // Drei Bytes schreiben...&lt;br /&gt;
  i2c_write(byte2); &lt;br /&gt;
  i2c_write(byte3); &lt;br /&gt;
  i2c_stop();       // Zugriff beenden&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
  i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
  byte1= i2c_readAck(); // Bytes lesen...&lt;br /&gt;
  byte2= i2c_readAck();&lt;br /&gt;
  byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK&lt;br /&gt;
  i2c_stop();           // Zugriff beenden&lt;br /&gt;
} &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ((byte1 != 42)||(byte2 != 43)||(byte3 != 44))&lt;br /&gt;
{&lt;br /&gt;
  /* Die Bytes wurden nicht korrekt übertragen und wieder gelesen! */ &lt;br /&gt;
}&lt;br /&gt;
    for(;;);	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Code wurde von HannoHupmann auf einem Mega32 getestet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slave == &lt;br /&gt;
Hier soll nun der Code behandelt werden der für den Slave-Controller notwendig ist. Der vorgestellte Code schreibt die Register des Slaves an die Serielle Schnittstelle, mit einem Terminal Programm kann man sich die Ausgabe ansehen und überprüfen ob alles korrekt funktioniert. &lt;br /&gt;
Der Code ist wieder an den von Peter Fleury angelehnt.&lt;br /&gt;
&lt;br /&gt;
Der Slave sollte ohne Master folgende Ausgabe liefern: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
10&lt;br /&gt;
11&lt;br /&gt;
12&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
Die Register werden der Reihe nach mit ihrem Wert angezeigt. Wird der Master hinzugefügt sollte nun folgende Ausgabe im Terminal erscheinen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdata: &lt;br /&gt;
42&lt;br /&gt;
43&lt;br /&gt;
44&lt;br /&gt;
13&lt;br /&gt;
usw. &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für den Slave &lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
Nun kann man dort sehen, wenn der Master einen Wert ändert&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		//enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		//definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;i2c_buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
_delay_ms(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 5.4.2010 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;         //definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
//Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht!&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 10// I2C_REG_ANZAHL 254 Hier kann eingestellt werden wieviele Register ausgegeben werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16171</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16171"/>
				<updated>2010-04-05T16:39:30Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Master */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master.&lt;br /&gt;
&lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Codeschnipsel für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden drei Bytes erst in den Slave geschrieben, und anschließend wieder ausgelesen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot;  //I2C-Master-Routinen von Peter Fleury verwenden (siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs)&lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
&lt;br /&gt;
uint8_t byte1 = 42;&lt;br /&gt;
uint8_t byte2 = 43;&lt;br /&gt;
uint8_t byte3 = 44;&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00);  // Buffer Startadresse setzen 	&lt;br /&gt;
  i2c_write(byte1); // Drei Bytes schreiben...&lt;br /&gt;
  i2c_write(byte2); &lt;br /&gt;
  i2c_write(byte3); &lt;br /&gt;
  i2c_stop();       // Zugriff beenden&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
  i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
  byte1= i2c_readAck(); // Bytes lesen...&lt;br /&gt;
  byte2= i2c_readAck();&lt;br /&gt;
  byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK&lt;br /&gt;
  i2c_stop();           // Zugriff beenden&lt;br /&gt;
} &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ((byte1 != 42)||(byte2 != 43)||(byte3 != 44))&lt;br /&gt;
{&lt;br /&gt;
  /* Die Bytes wurden nicht korrekt übertragen und wieder gelesen! */ &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		//enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		//definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
//Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht!&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 8  //Beispiel: acht Register&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/*@}*/&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für die twislave.c&lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Funktion für Warteschaleifen&lt;br /&gt;
//Parameter: Wartezeit in Milisekunden&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
void warte (int loop)  //loop: wartezeit in ms &lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;loop;i++) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
warte(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16170</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16170"/>
				<updated>2010-04-05T16:10:33Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Master */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master.&lt;br /&gt;
&lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Codeschnipsel für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden drei Bytes erst in den Slave geschrieben, und anschließend wieder ausgelesen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.c&amp;quot;  //I2C-Master-Routinen von Peter Fleury verwenden (siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs)&lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
&lt;br /&gt;
uint8_t byte1 = 42;&lt;br /&gt;
uint8_t byte2 = 43;&lt;br /&gt;
uint8_t byte3 = 44;&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00);  // Buffer Startadresse setzen 	&lt;br /&gt;
  i2c_write(byte1); // Drei Bytes schreiben...&lt;br /&gt;
  i2c_write(byte2); &lt;br /&gt;
  i2c_write(byte3); &lt;br /&gt;
  i2c_stop();       // Zugriff beenden&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
  i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
  byte1= i2c_readAck(); // Bytes lesen...&lt;br /&gt;
  byte2= i2c_readAck();&lt;br /&gt;
  byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK&lt;br /&gt;
  i2c_stop();           // Zugriff beenden&lt;br /&gt;
} &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ((byte1 != 42)||(byte2 != 43)||(byte3 != 44))&lt;br /&gt;
{&lt;br /&gt;
  /* Die Bytes wurden nicht korrekt übertragen und wieder gelesen! */ &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		//enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		//definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
//Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht!&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 8  //Beispiel: acht Register&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/*@}*/&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für die twislave.c&lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Funktion für Warteschaleifen&lt;br /&gt;
//Parameter: Wartezeit in Milisekunden&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
void warte (int loop)  //loop: wartezeit in ms &lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;loop;i++) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
warte(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16168</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16168"/>
				<updated>2010-04-05T16:07:06Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Master */ Codebeispiel erweitert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master.&lt;br /&gt;
&lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Codeschnipsel für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden die ersten drei Bytes aus dem txbuffer des Slaves gelesen und in byte0..2 abgespeichert.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.c&amp;quot;  //I2C-Master-Routinen von Peter Fleury verwenden (siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs)&lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
&lt;br /&gt;
uint8_t byte1 = 42;&lt;br /&gt;
uint8_t byte2 = 43;&lt;br /&gt;
uint8_t byte3 = 44;&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00);  // Buffer Startadresse setzen 	&lt;br /&gt;
  i2c_write(byte1); // Drei Bytes schreiben...&lt;br /&gt;
  i2c_write(byte2); &lt;br /&gt;
  i2c_write(byte3); &lt;br /&gt;
  i2c_stop();       // Zugriff beenden&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
{&lt;br /&gt;
  i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
  i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
  byte1= i2c_readAck(); // Bytes lesen...&lt;br /&gt;
  byte2= i2c_readAck();&lt;br /&gt;
  byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK&lt;br /&gt;
  i2c_stop();           // Zugriff beenden&lt;br /&gt;
} &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Hier könnte eine Fehlermeldung ausgegeben werden... */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ((byte1 != 42)||(byte2 != 43)||(byte3 != 44))&lt;br /&gt;
{&lt;br /&gt;
  /* Die Bytes wurden nicht korrekt übertragen und wieder gelesen! */ &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		//enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		//definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
//Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht!&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 8  //Beispiel: acht Register&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/*@}*/&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für die twislave.c&lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Funktion für Warteschaleifen&lt;br /&gt;
//Parameter: Wartezeit in Milisekunden&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
void warte (int loop)  //loop: wartezeit in ms &lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;loop;i++) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
warte(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16101</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=16101"/>
				<updated>2010-03-30T18:30:33Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Slave header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master.&lt;br /&gt;
&lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Codeschnipsel für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden die ersten drei Bytes aus dem txbuffer des Slaves gelesen und in byte0..2 abgespeichert.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.c&amp;quot;  //I2C-Master-Routinen von Peter Fleury verwenden (siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs)&lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
uint8_t byte0;&lt;br /&gt;
uint8_t byte1;&lt;br /&gt;
uint8_t byte2;&lt;br /&gt;
&lt;br /&gt;
      if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
      {&lt;br /&gt;
         i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
         i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
            byte0= i2c_readAck();&lt;br /&gt;
            byte1= i2c_readAck();&lt;br /&gt;
            byte2= i2c_readNak(); //letztes Byte lesen, darum kein ACK&lt;br /&gt;
         i2c_stop();&lt;br /&gt;
      } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		//enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		//definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
//Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht!&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size 8  //Beispiel: acht Register&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/*@}*/&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für die twislave.c&lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Funktion für Warteschaleifen&lt;br /&gt;
//Parameter: Wartezeit in Milisekunden&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
void warte (int loop)  //loop: wartezeit in ms &lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;loop;i++) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
warte(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=%C3%84tzger%C3%A4t_Bauanleitung&amp;diff=16037</id>
		<title>Ätzgerät Bauanleitung</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=%C3%84tzger%C3%A4t_Bauanleitung&amp;diff=16037"/>
				<updated>2010-03-19T19:41:09Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Selbstbauanleitung für ein 1–Liter-Ätzgerät ==&lt;br /&gt;
(Volumen für 0,5 l Ätzlösung)&lt;br /&gt;
&lt;br /&gt;
Für Leiterplatten im Europaformat (100mm x 160 mm)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_InAction_.jpg|640px|center]]&lt;br /&gt;
(Die Luftblasen werden im laufenden Betrieb noch feiner und kleiner)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bitte diese Anleitung zunächst komplett durchlesen, &lt;br /&gt;
bevor mit dem Nachbau und dem Materialeinkauf begonnen wird.&lt;br /&gt;
&lt;br /&gt;
== Beschreibung des verwendeten Materials ==&lt;br /&gt;
Die meisten Materialien bekommt man &lt;br /&gt;
* im Baumarkt (BayWa, Hornbach, Max Bahr, OBI Baumarkt, Praktiker, TOOM ect.pp.) &lt;br /&gt;
* Aquariumszubehör (auch in vielen OBI Märkten)&lt;br /&gt;
Ja, ihr habt richtig gelesen, genau die gleichen Materialien wie in der vorliegenden Bauanleitung bekommt man zwar im einschlägigen Elektronik-Fachmarkt, sind dort jedoch um ein Vielfaches teurer als im Aquariumzubehörhandel.&lt;br /&gt;
&lt;br /&gt;
==== Glasplatten ====&lt;br /&gt;
Sämtliche Glasplatten sollten, sofern verfügbar, eine Stärke von 5 mm haben.&lt;br /&gt;
Geringere Plattenstärken sind anfälliger für Bruch oder Risse.&lt;br /&gt;
&lt;br /&gt;
Von Kunststoffglas wie Plexi- oder Acrylglas rate ich ab, da dies matt und bei den im Ätzprozess verwendeten Temperaturen (50°C bis 80°C) brüchig wird. Außerdem lässt sich Glas (mit entsprechender Übung) besser und einfacher verarbeiten. Glas ist, entgegen verbreiteter Meinung, sehr leicht zu verarbeiten, wenn man sich an gewisse Regeln hält und etwas Übung hat. Wer den Zuschnitt von Glas scheut, kann sich beim Glaser entsprechende (fertige) Zuschnitte (aus Resten) besorgen. Die Reste dürften auch relativ günstig zu erstehen sein. Eine geschnittene (sauber gebrochene) Glasplatte hat im Gegensatz zu gesplittertem Glas keine so scharfen Kanten, jedenfalls sind diese bei weitem nicht so gefährlich. Trotzdem sollten die Kanten abgestumpft werden, außerdem begünstigt dies auch das Verkleben der Glasplatten untereinander. Hierzu reicht es meist aus die Kanten z.B. mit einem Edelkorund oder Diamantschleifstift (wie für viele Mini–Bohrmaschinen erhältlich) zu entgraten. Wer hat, darf natürlich auch seine Glasschleifmaschine (wie für Tiffany-Glastechnik) einsetzen.&lt;br /&gt;
&lt;br /&gt;
==== Luftverteiler für Umwälzung ====&lt;br /&gt;
(Aquaristik) Air Curtain. Ein poröser Schlauch, durch welchen die eingeblasene Luft über dessen gesamte Länge in kleinen Bläschen austritt. Diese Bläschen sorgen durch ihr Aufsteigen dafür, dass das Ätzbad in Bewegung kommt, um so eine gleichmäßige Temperatur über die gesamte Apparatur zu gewährleisten und das Aufheizen zu beschleunigen und zum anderen, dass die Leiterplatte schneller und gleichmäßiger geätzt wird. Andere Möglichkeiten das Ätzbad umzuwälzen, z.B. durch Umpumpen, sind für diese Anwendung finanziell nicht akzeptabel, da alle Komponenten säurefest sein müssten.&lt;br /&gt;
&lt;br /&gt;
==== Membran-Luftpumpe ====&lt;br /&gt;
(Aquaristik) diese sorgt für die benötigte Luft des Luftverteilers &lt;br /&gt;
&lt;br /&gt;
==== Rücklaufstopp (Ventil) ====&lt;br /&gt;
(Aquaristik) um zu verhindern, dass Ätzlösung über den Luftschlauch in die Luftpumpe und aus dem Gerät ausläuft ist diese geringe Investition ein absolutes Muss&lt;br /&gt;
&lt;br /&gt;
==== PVC-Luftschlauch ====&lt;br /&gt;
(Baumarkt) (Aquaristik) verbindet die Luftpumpe über das Ventil mit dem Luftverteiler.&lt;br /&gt;
&lt;br /&gt;
==== Latex Luftschlauch ====&lt;br /&gt;
(Baumarkt) (Aquaristik) aus Latex lieber als aus PVC; säurebeständiger. Schlauch aus PVC wird mit der Zeit porös. 4.99 €&lt;br /&gt;
&lt;br /&gt;
==== Heizelement ====&lt;br /&gt;
(Aquaristik/Elektronik Bedarf) sorgt für die benötigte Temperatur. Ein in einem Glaskolben wasserdicht eingebautes Heizelement mit Thermostat, welches in die Lösung eintaucht und diese erwärmt.&lt;br /&gt;
&lt;br /&gt;
==== Thermometer ====&lt;br /&gt;
Um die Temperatur zu kontrollieren und das Heizelement einzustellen, braucht man ein Thermometer. Es sollte komplett aus Glas sein, damit es säurefest ist. Solche Thermometer bekommt man zum Beispiel im Teeladen. &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Wer sich aufgrund fehlender Infos oder Datenblätter nicht entscheiden kann und dennoch eine zuverlässige Heizung erstehen möchte, dem sind von mir folgende Heizungen empfohlen: &lt;br /&gt;
&lt;br /&gt;
'''Von Reichelt:''' Heizung0 (100W) € 31,65 € - Heizung1 (100W) 19,95 € - Heizung2 (150W) 23,95 €&lt;br /&gt;
&lt;br /&gt;
'''Von Conrad:''' 552020 - 62 € 32,24  - 530425 - 62 (150W) € 35,46&lt;br /&gt;
&lt;br /&gt;
(Preisinfo vom 19.03.2010)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== Silikon und Pistole für die Kartusche ====&lt;br /&gt;
(Baumarkt) Sanitärsilikon (essigvernetzt) für Glasabdichtung / Verklebung. Bitte kein Acryl oder sonstiges Fugen- oder Bausilikon verwenden, dies haftet nicht so gut, dichtet nicht wie benötigt und wird auf Dauer gesehen brüchig und undicht. &lt;br /&gt;
&lt;br /&gt;
==== Fugenhilfe ==== &lt;br /&gt;
Ein aus PVC bestehendes Fugenprofil hilft die Silikonnähte sauber zu verstreichen. Die Zeiten, in welchen man das Silikon mit dem in Spülmittel getränktem Finger verstrichen hat, sind ein für allemal vorbei. In einigen Home-Shopping-Sendern auch als „Fugi“ beworben und hat nichts mit Pilzen zu tun. &lt;br /&gt;
&lt;br /&gt;
==== Kunststoffprofile und Kunststoffplatten ====&lt;br /&gt;
(Baumarkt) Zur Erstellung der Halter für die Leiterplatten und als Montagegerüst für den Luftverteiler sowie des Heizelementes.&lt;br /&gt;
&lt;br /&gt;
== Dimensionierung ==&lt;br /&gt;
Bevor wir uns an die Materialbeschaffung machen und uns mit der Größe befassen, müssen wir einiges berücksichtigen: Breite der Glasküvette: Das Heizelement befindet sich in einem Glaskolben, welcher einen Durchmesser von mind. 20 mm hat. Somit entspricht die Breite der Glasküvette mindestens diesem Maß. Länge der Glasküvette: Die Länge der Glasküvette richtet sich nach mehreren Faktoren: &lt;br /&gt;
* Durchmesser des Heizelements + Spielraum&lt;br /&gt;
* Breite der maximalen Leiterplattenbreite (welche geätzt werden kann/soll)&lt;br /&gt;
* Breite der Halterung + Spielraum für die Leiterplatte, um diese ins Ätzbad tauchen und herausnehmen zu können.&lt;br /&gt;
* Platz für den Luftschlauch, welcher den Luftverteiler versorgt&lt;br /&gt;
Die Höhe der Glasküvette ist vom Volumen abhängig, Breite und Länge sowie Verdrängung des Heizelementes und der Halter + Abstand, damit die Luftbläschen, welche ebenfalls die Lösung verdrängen und somit den Pegel anheben und die aufsteigenden (welche auf der Oberfläche zerplatzen und daher spritzen) die Küvette nicht zum Überlaufen bringen. Für den Luftverteilschlauch (am Boden der Küvette) muss ebenfalls etwas Platz berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Prinzipielle Bestimmung der Glasküvettengröße''' &lt;br /&gt;
&lt;br /&gt;
Innenmaße&lt;br /&gt;
{|{{Blauetabelle}}&lt;br /&gt;
&lt;br /&gt;
|Breite:&lt;br /&gt;
|25mm&lt;br /&gt;
|20mm Heizelement + 5mm Spielraum &lt;br /&gt;
|-&lt;br /&gt;
|Länge:&lt;br /&gt;
|210mm	&lt;br /&gt;
|160mm Leiterplatte&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|2x 20mm für die Halter&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|10mm für den Luftschlauch&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|20mm Heizelement&lt;br /&gt;
|-&lt;br /&gt;
|Höhe:&lt;br /&gt;
|220mm&lt;br /&gt;
|Volumen / Breite / Länge = Höhe + Spielraum&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Volumen sollte 1 l betragen (1000000 mm³)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|1000000 / 210 / 25 ~ 190,5 mm + 30 mm Spielraum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Mit etwas angepassten Werten&lt;br /&gt;
(damit das Ganze etwas ansprechender aussieht):&lt;br /&gt;
{|&lt;br /&gt;
|B&lt;br /&gt;
|=&lt;br /&gt;
|25 mm&lt;br /&gt;
|-&lt;br /&gt;
|L&lt;br /&gt;
|=&lt;br /&gt;
|230 mm&lt;br /&gt;
|-&lt;br /&gt;
|H&lt;br /&gt;
|=&lt;br /&gt;
|200 mm&lt;br /&gt;
|}&lt;br /&gt;
Mit diesen Werten kann eine Europaplatine (160 mm x 100 mm) spielend „gebadet“ werden.&lt;br /&gt;
Bestimmung der Glasplattengröße.&lt;br /&gt;
Da sich Glasplatten mit einer Stärke von 5 mm und einer Breite von 25 mm nur für sehr geübte Hobbyglaser verarbeiten lassen, wähle ich eine breitere Variante, welche an den Stirnseiten verklebt wird; die verleiht der Glasküvette außerdem einen besseren Stand.&lt;br /&gt;
&lt;br /&gt;
=== Glaszuschnitte === Maße etwas abgeändert:&lt;br /&gt;
{|{{Blauetabelle}}&lt;br /&gt;
|Seitenteile:&lt;br /&gt;
| 2x&lt;br /&gt;
|Glasplatte a '''5 mm''' (Stärke) x &lt;br /&gt;
'''220 mm''' (Höhe) '''x 55 mm''' (Tiefe)&lt;br /&gt;
|-&lt;br /&gt;
|Vorder/Rückseiten:&lt;br /&gt;
| 2x&lt;br /&gt;
|Glasplatte a '''5 mm''' (Stärke) x &lt;br /&gt;
'''210 mm''' (Breite) '''x 220 mm''' (Höhe)&lt;br /&gt;
|-&lt;br /&gt;
|Fußplatte:&lt;br /&gt;
| 1x&lt;br /&gt;
|Glasplatte a '''5 mm''' (Stärke) x &lt;br /&gt;
'''220 mm''' (210 mm + 10 mm (Breite + Überhang)) '''x 55 mm''' (Tiefe)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Nachbau Schritt für Schritt ==&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Schleifen1.jpg|thumb|right|Stumpfschleifen mit einer Glasschleifmaschine]][[Bild:Bauanleitung-Ätzgerät_Schleifen2.jpg|thumb|right|Kanten mit einem Edelkorund stumpfschleifen]]&lt;br /&gt;
ACHTUNG: '''Immer mit Schutzbrille arbeiten!'''&lt;br /&gt;
&lt;br /&gt;
Besonders beim Schleifen springen feine Glassplitter herum, welche die Augen verletzen können.&lt;br /&gt;
&lt;br /&gt;
===Materialbearbeitung===&lt;br /&gt;
* 1. Die Glasplatten werden den Abmessungen entsprechend zugeschnitten (gebrochen)&lt;br /&gt;
TIPP:&lt;br /&gt;
Wer sein Glas selbst schneiden will, dem sei folgender Hinweis gegeben.&lt;br /&gt;
Die Bruchstelle wird sauberer, wenn man den Schnitt vor dem Brechen mit Wasser vernetzt.&lt;br /&gt;
Noch bessere Ergebnisse erzielt man, wenn man den Glasschneider mit Schneidöl (Kriechöl wie z.B. Balistol) tränkt. &lt;br /&gt;
&lt;br /&gt;
Es gibt sogar Glasschneider mit eingebautem Öltank, diese kosten ab € 35,- aber dies ist für nur einmaligen Gebrauch etwas zuviel. &lt;br /&gt;
&lt;br /&gt;
Einen sauberen Schnitt kann man kaum erkennen, ist die Schnittlinie hingegen deutlich sichtbar (ausgefranst,) deutet dies auf eine ungenaue Schnittführung oder einen defekten Glasschneider hin. Man kann sogar während des Anschneidens hören ob dieser gelingt oder unsauber wird (Übung ist alles). Mit unsauberen Schnittlinien wird dann auch die Bruchstelle unregelmäßig und „fransig“ oder wellig.&lt;br /&gt;
Ein gemäßigter nicht zu kräftiger Schlag auf die dem Schnitt abgewandten Seite der Platte lässt diese einreißen. Ein dünnes Hölzchen (Zahnstocher) direkt unter den Schnitt gelegt und mit den Daumen soweit wie möglich links und rechts vom Schnitt entfernt auf die Glasplatte drücken (Knack).&lt;br /&gt;
&lt;br /&gt;
* 2. Die Kanten müssen geschliffen (entgratet) werden, damit man sich nicht daran verletzen und der Silikon-Kleber besser haften kann (bessere Verbindung).&lt;br /&gt;
Dies kann, falls verfügbar, mit einem Glasschleifgerät (Diamantschleifkopf) oder mit weniger Aufwand aber ebenso effektiv, mit einer Minibohrmaschine und einem Edelkorund-Schleifstein erfolgen. &lt;br /&gt;
&lt;br /&gt;
Auch mit Korund beschichtetes Schleifpapier (Teller-Schleifgeräte) kann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verkleben der einzelnen Teile ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Verkleben1.jpg|thumb|right|Silikonauftrag]][[Bild:Bauanleitung-Ätzgerät_Verkleben2.jpg|thumb|right|Immer einen dünnen aber mit Silikon lückenlos gefüllten Spalt lassen (elastische Fuge)]][[Bild:Bauanleitung-Ätzgerät_Verkleben3.jpg|thumb|right|ungenutzte Glasplatten dienen als Abstandshalter bis das Silikon getrocknet ist]][[Bild:Bauanleitung-Ätzgerät_Verkleben6.jpg|thumb|right|Silikon auftragen]][[Bild:Bauanleitung-Ätzgerät_Verkleben5.jpg|thumb|right|Glasplatte nur leicht andrücken, wieder einen schmalen, aber mit Silikon lückenlos gefüllten Spalt lassen]]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Glasplatten werden mit Silikon verklebt. Nur essigvernetztes Sanitärsilikon verwenden, transparent oder gefärbt ist egal.&lt;br /&gt;
Acryl oder Bausilikon ist ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Um eine einwandfreie Klebestelle zu gewährleisten müssen die betroffenen Stellen absolut sauber, trocken und fettfrei sein. Auch Fingerabdrücke beeinflussen die Klebekraft.&lt;br /&gt;
Am besten die entsprechenden Stellen unmittelbar vorher mit ACETON und einem Küchenkrepp reinigen. Nagellackentferner enthält oft auch Aceton, ist aber wegen der beigemengten Öle und Pflegemittel ungeeignet.&lt;br /&gt;
„Normales“ Aceton ist im Baumarkt oder in einer Drogerie erhältlich.&lt;br /&gt;
&lt;br /&gt;
====Rückwärtiges- und Bodenteil====&lt;br /&gt;
Die ersten beiden Bauteile werden zusammengefügt.&lt;br /&gt;
&lt;br /&gt;
Nicht Platte an Platte pressen, sondern einen hauchdünnen Spalt ohne Lufteinschlüsse lassen.&lt;br /&gt;
So bleibt die Fuge elastisch und kann besser trocknen.&lt;br /&gt;
&lt;br /&gt;
Kleinere Fehlstellen ohne dichte Verklebung sind hier zunächst nicht so tragisch. Die endgültige Dichtigkeit wird am Schluss sichergestellt.&lt;br /&gt;
Hier geht es zunächst um die mechanische Stabilität. Nicht alle Bauteile auf einmal zusammenfügen, hier ist viel Geduld notwendig. Zunächst sollte die erste Verbindung aushärten, bevor man mit der nächsten weitermacht. Dies kann durchaus einen ganzen Tag dauern (je nach Silikon). Oberflächlich getrocknetes Silikon ist im Kern noch lange nicht fest, daher lieber etwas mehr Zeit verstreichen lassen als zuwenig. Im schlimmsten Falle haften die einzelne Teile nicht fest genug aneinander. Nach ca. 12h dürfte allerdings eine genügende Trocknung erreicht sein. &lt;br /&gt;
Jetzt darf diese erste Klebestelle erst einmal bis zur Festigkeit austrocknen.&lt;br /&gt;
&lt;br /&gt;
==== Frontseitiges- und Bodenteil ====&lt;br /&gt;
Ist diese erste Verklebung nun getrocknet, legt man wieder einige Reststücke von den Glasplatten oder was man sonst so findet, um die 2. Platte mit einem Abstand (25 mm) auflegen zu können. Wichtig ist, dass die Platte stabil zu liegen kommt und nicht verwackelt sowie dass die Ränder frei bleiben.&lt;br /&gt;
Diesmal sollten es aber so ziemlich genau die berechneten 25 mm sein.&lt;br /&gt;
&lt;br /&gt;
Auf diesen Abstandshalter legt man dann die zweite, mit an der eine Kante mit Silikon vorbereitete Glasplatte und bringt diese in Stellung (Kontakt mit geringem Spalt zur Bodenplatte, so dass das Silikon gut anhaftet). &lt;br /&gt;
Nicht Platte an Platte pressen, sondern einen hauchdünnen Spalt ohne Lufteinschlüsse lassen.&lt;br /&gt;
Nun wieder warten, bis die Klebestelle getrocknet ist und ihre Endfestigkeit erreicht hat &lt;br /&gt;
(über Nacht {mind. 8h} dürfte auch hier reichen, aber wie erwähnt, lieber länger warten als zu kurz).&lt;br /&gt;
&lt;br /&gt;
==== Seitenteile ====&lt;br /&gt;
Nachdem die Silikonnähte der Front- und Rückseite an der Bodenplatte wirklich Endfestigkeit haben, drehen wir diese so um 90°, dass der Aufbau auf einem Seitenteil zu stehen kommt.&lt;br /&gt;
Jetzt ist etwas mehr Sorgfalt angesagt.&lt;br /&gt;
&lt;br /&gt;
Den inneren Abstand der Küvette fixieren wir wieder mit den Teilen, welche schon zuvor den Abstand bestimmt haben. An der offenen Seite fixieren wir die Platten z.B. mit Klebeband, so dass diese nicht aus Versehen auffächern können. Somit ist über die gesamte Höhe ein gleichmäßiger Abstand gewährleistet.&lt;br /&gt;
Jetzt noch die Platten so ausrichten, dass diese im rechten Winkel zueinander stehen.&lt;br /&gt;
Auf die Kanten wird wieder das Silikon aufgetragen.&lt;br /&gt;
Hier ist es ratsam besonders in den Ecken keine „offene“ Stelle zu haben, da dies ein besonders kritischer Bereich ist.&lt;br /&gt;
&lt;br /&gt;
Jetzt wieder trocknen lassen ...&lt;br /&gt;
Danach genauso mit der gegenüberliegenden Seite verfahren.&lt;br /&gt;
&lt;br /&gt;
=== Finishing ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Finishing1.jpg|thumb|right|Finishing]] [[Bild:Bauanleitung-Ätzgerät_Dichtetest1.jpg|thumb|right|Dichte-Test mit Wasser]]&lt;br /&gt;
Das Finishing entscheidet letztendlich ob unsere Glasküvette dicht wird oder ob diese leckt.&lt;br /&gt;
Zunächst entfernen wir die herausgequollenen „Silikonwürste“ auf der Außenseite mit einem Cuttermesser. Auf der Innenseite ist dieses herausgequollene Silikon nicht störend (nur optisch). &lt;br /&gt;
* '''Achtung:''' nicht in die Fuge hineinschneiden, sondern nur das überstehende Material entfernen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Erster Dichtigkeitstest ===&lt;br /&gt;
Die Küvette mit Wasser füllen und entsprechende Stellen, an welchen Wasser austritt, &lt;br /&gt;
mit Filzstift oder Fettstift markieren. Diese Stellen müssen im letzten Schritt besonders beachtet und abgedichtet werden &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fugen mit der Fugenhilfe nacharbeiten ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Fugi1.jpg|thumb|right|Silikon-Fugenhilfe]]&lt;br /&gt;
Jetzt kommt das auch als „Fugi“ bekanntes Werkzeug zum Einsatz.&lt;br /&gt;
Natürlich muss es nicht das Original aus dem TV-Shopping sein, auch im Baumarkt bekommt man ein entsprechendes äquivalentes Werkzeug.&lt;br /&gt;
Wählt einen eurer Meinung nach einen passenden Radius an der Fugenhilfe aus.&lt;br /&gt;
Natürlich muss wieder alles trocken, sauber, staub- und fettfrei sein, sonst ist alles umsonst. &lt;br /&gt;
&lt;br /&gt;
'''Pauschal alles noch mal mit Aceton (fettlösend) reinigen'''.&lt;br /&gt;
&lt;br /&gt;
In den bereinigten Kanten an den Fugen wird nun nochmals frisches Silikon aus der Kartusche aufgetragen und mit der Fugenhilfe geformt und geglättet. &lt;br /&gt;
Nicht zu viel und nicht zu wenig Silikon auftragen und vor allem gleichmäßig. &lt;br /&gt;
Wie viel ihr verwenden müsst, bekommt ihr mit der ersten Fuge schnell heraus (Don’t Panic).&lt;br /&gt;
Nicht alle Fugen auf einmal nacharbeiten, erst die eine, dann die nächste Fuge.&lt;br /&gt;
&lt;br /&gt;
Durch die genaue Führung mit der Fugenhilfe kann „nass in nass“ gearbeitet werden, &lt;br /&gt;
d.h es muss hier nicht immer wieder gewartet werden bis alles getrocknet ist. &lt;br /&gt;
Es geht eigentlich alles fix und sehr sauber.&lt;br /&gt;
&lt;br /&gt;
=== Handhabung der Fugenhilfe ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Fugi2.jpg|thumb|right|Silikon-Fugenhilfe anwenden]]&lt;br /&gt;
Die Fugenhilfe wird so geführt, dass diese an den beiden Glasplatten anliegt um so überschüssiges Silikon abzuziehen.&lt;br /&gt;
Dabei nicht in Richtung der abgeschrägten Seite ziehen, sondern in die Richtung ziehen, zu welcher die flache Seite schaut (im Bild die abgewandte Seite).&lt;br /&gt;
In einem Zug ohne Unterbrechung das Silikon „abziehen“. &lt;br /&gt;
Ist eine Stelle mit zu wenig Silikon vorhanden einfach die betreffende Stelle mit frischem Silikon aus der Tube auffüllen und gleich noch einmal abziehen. &lt;br /&gt;
Die Fugenhilfe immer vor dem Abziehen von Silikon befreien (mit Küchenkrepp abwischen) „sonst verschmiert’s alles“&lt;br /&gt;
Übrigens: Mit Kreditkarten oder anderen Plastikkarten funktioniert dies nicht, dann lieber wieder mit dem &amp;quot;nassen Finger&amp;quot; arbeiten.&lt;br /&gt;
&lt;br /&gt;
== Ein- und Anbauarbeiten ==&lt;br /&gt;
=== Luftverteiler ===&lt;br /&gt;
Hierfür benötigen wir &lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_AirCurtain.jpg|thumb|right|AirCurtain und Rücklaufstopp-Ventil]]&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Luftverteiler_Base1.jpg|thumb|right|Halter für Luftverteiler]]&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Luftverteiler_Base2.jpg|thumb|right|Luftverteiler auf Halter fixieren]]&lt;br /&gt;
eine Sprudelquelle (Air Curtain), &lt;br /&gt;
einen PVC-Schlauch, &lt;br /&gt;
ein Rückschlagventil und &lt;br /&gt;
ein Kunststoffprofil sowie &lt;br /&gt;
etwas Silikon und&lt;br /&gt;
Frischhaltefolie.&lt;br /&gt;
Natürlich auch eine elektrische Luft- bzw. Membranpumpe.&lt;br /&gt;
&lt;br /&gt;
Um zu verhindern, dass der Sprudelschauch nach oben treibt, verankern wir diesen auf einem Kunststoffprofil und fixieren den Schlauch mit Silikon, da dies gegen die Ätzbäder resistent ist.&lt;br /&gt;
Silikon haftet aber nicht auf allen Materialien, speziell nicht auf PVC und ähnlichen Kunststoffen, so behelfen wir uns mit einem Trick:&lt;br /&gt;
Das Kunststoffprofil hat in etwa die Abmessungen der Innenfläche unserer Glasküvette, eher etwas kleiner. Dieses Kunststoffprofil bohren wir in regelmäßigen Abständen mit ca. 4 mm durch und senken diese auf der Unterseite großzügig an. Auf diese Bohrungen geben wir großzügig Silikon, so dass dieses durch die Bohrung auf der anderen Seite austritt, zusätzlich legen wir einen Silikonstrang quer zum Profil auf.&lt;br /&gt;
&lt;br /&gt;
Diese so vorbereitete Profil legen wir auf Frischhaltefolie, da diese später leicht vom getrockneten Silikon entfernt werden kann.&lt;br /&gt;
Darauf legen wir dann den vorher abgelängten „Air Curtain“-Schlauch und fixieren diesen wiederum mit Silikonsträngen. Diese „Konstruktion“ lassen wir über Nacht trocknen.&lt;br /&gt;
&lt;br /&gt;
Da das Silikon in die Senkungen gepresst wird hält dies mechanisch, sozusagen wie ein Niet oder Druckknopf, den Luftverteiler am Profil. Das an den Seiten überstehende Silikon kann nach dem Austrocknen problemlos abgeschnitten werden oder mit Hilfe der Frischhaltefolie im feuchten Zustand in die Fugen unter dem Schlauch verteilt werden. &lt;br /&gt;
&lt;br /&gt;
Das '''Silikon nicht über die gesamte Schlauchlänge verteilen''', da sonst keine Luft mehr austreten kann. Nach dem Abbinden des Silikons können die überstehenden Reste abgeschnitten werden und dann wird abschließend der PVC-Schlauch angeschlossen und dieser Luftverteiler, evtl. wieder mit etwas (sehr wenig) Silikon, am Glasküvettenboden fixiert.&lt;br /&gt;
&lt;br /&gt;
=== Heizelement ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Heizelement_Halter.jpg|thumb|right|Heizungshalter]]&lt;br /&gt;
Für das Heizelement benötigen wir als Halter eigentlich nur ein Stück vom Kunststoffprofil, dessen Mindestabmessungen so groß sind, damit dieses nicht in die Küvette fallen kann und Platz für eine Bohrung bietet, damit dieses über den Glaskolben des Heizelementes geschoben werden kann ohne dass dieses komplett durchrutschen kann.&lt;br /&gt;
Die abgebildete Version zeigt den Halter mit einer zusätzlichen Bohrung zur Durchführung des Luftschlauches für den Luftverteiler.&lt;br /&gt;
&lt;br /&gt;
=== Leiterplattenhalter ===&lt;br /&gt;
Der Leiterplattenhalter muss mehrere Eigenschaften besitzen.&lt;br /&gt;
* zum einen soll die Leiterplatte sicher gehalten werden,&lt;br /&gt;
* zum anderen muss die Leiterplatte auch am Rand von der Ätzlösung umspült werden können&lt;br /&gt;
* und nicht zuletzt muss der Halter an unterschiedliche Leiterplattengrößen angepasst werden können.&lt;br /&gt;
&lt;br /&gt;
Eine nahezu perfekte Lösung dieser gestellten Probleme bieten die u.a. von der Fa. ISEL auch einzeln erhältlichen Leiterplattenhalter, welche auch auf die Abmessungen unserer selbst gebauten Ätzmaschiene angepasst werden kann.&lt;br /&gt;
* '''Achtung:''' Wenn z.B. der ISEL Platinenhalter gekauft wird, reicht der Platz für eine Europaplatine (100x160mm) nicht mehr aus, da der Halter breiter ist als der hier im folgenden beschriebene Selbstbauhalter. Es können dann eben nur schmälere (max. 100x120mm) Platinen geätzt werden.&lt;br /&gt;
Aber was wäre das denn für eine Bauanleitung, wenn nicht auch alles selbst gebaut bzw. beschrieben wird? (So einfach mache ich es mir dann doch nicht.)&lt;br /&gt;
Das Problem besteht darin, eine einfache und dennoch praktikable und relativ einfach nachzubildende Konstruktion zu finden. Die entsprechenden Profile, wie von Isel verwendet, sind nicht so leicht zu beschaffen.&lt;br /&gt;
Wir benötigen folgende Materialien:	&lt;br /&gt;
	Ein quadratisches Kunststoffvollprofil mit etwa 11mm (11,5mm) Kantenlänge&lt;br /&gt;
	ein flaches Kunststoffprofil mit etwa 3mm Stärke und ca. 35mm (35,5mm) Breite&lt;br /&gt;
	ein rundes Kunststoffvollprofil mit einem Durchmesser von ca. 7mm (7,5mm)&lt;br /&gt;
	Kunststoff- oder Blechschrauben 3,5 x 20mm (Linsenkopf)&lt;br /&gt;
Die quadratischen Profile werden auf eine Länge von ca. 19 cm geschnitten, an beiden Enden mit einem Abstand von ca. 1 cm und ca. 2 cm zur Kante mit einer 8-mm-Bohrung versehen und eine Nut in das Profil von Bohrung zu Bohrung gefräst.&lt;br /&gt;
&lt;br /&gt;
==== Eingefräste Nuten ====&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Leiterplattenhalter1.jpg|thumb|right|Platinenhalter Oberteil]][[Bild:Bauanleitung-Ätzgerät_Leiterplattenhalter2.jpg|thumb|right|Platinenhalter Seitenteile]][[Bild:Bauanleitung-Ätzgerät_Leiterplattenhalter3.jpg|thumb|right|Platinenhalter komplett montiert]]Zum Fräsen kann eine Mini-Bohrmaschine in einem Bohrständer fixiert und mit einem entspr. Fräsbohrer bestückt werden. Das Kunststoffprofil wird dann entweder in einem Schraubstock, in welchem das Profil locker geführt wird oder an einem entspr. Anschlag geführt, damit die Nut auch gleichmäßig geführt wird. Natürlich kann auch ein Kreuzfrästisch benutzt werden, aber wer hat denn schon so was (außer mir natürlich) in seiner Werkstatt.&lt;br /&gt;
&lt;br /&gt;
In die Bohrungen werden die runden, entsprechend gekürzten Kunststoffvollprofile gesteckt und später auf einer Seite verklebt, damit diese nicht herausrutschen können. Diese Stangen dienen später dazu, dass sich die Leiterplattenhalter, welche sich durch die Temperatur des Ätzbades verbiegen können, nicht zu stark auseinander biegen und somit die eingeklemmte Leiterplatte verlieren. Außerdem hat die Leiterplatte hiermit einen Halt und kann nicht aus der Halterung fallen.&lt;br /&gt;
&lt;br /&gt;
==== Deckelteil ==== &lt;br /&gt;
Deckelteil wird entsprechend der verbleibenden Länge aus dem flachen Kunststoffprofil gefertigt. (Die Breite der Glasküvette, abzüglich der Breite der Halterung für das Heizelement.&lt;br /&gt;
Dann wird eine Nut eingefräst, in der dann mittels Schrauben die quadratischen Halter befestigt werden. Die Nuten sollten einen Abstand zum Rand von ca. 1 cm und untereinander einen Abstand von ca. 4 cm haben, somit hat der Deckelteil noch genügend Stabilität, um nicht auseinander zu brechen und die gesamte Aufhängung am Küvettenrand zu halten.&lt;br /&gt;
&lt;br /&gt;
==== Montage des Leiterplattenhalters ====&lt;br /&gt;
Die beiden bearbeiteten Vierkantprofile werden an einer Seite (größerer Abstand zu den Stabis) für die Schraubenaufnahme angebohrt. Mittels Schrauben werden diese am Deckelteil befestigt und die Rundstäbe durch die Bohrungen geführt. Die in die Vierkantprofile eingefrästen Nuten zeigen zueinander. Die Rundstäbe werden beide an einer Seite mit Kleber fixiert oder besser an einem Ende erhitzt und breit gedrückt (breiter als die Bohrungen im Halter).&lt;br /&gt;
&lt;br /&gt;
== Endmontage ==&lt;br /&gt;
Die fertige Ätzmaschine kann jetzt in Betrieb genommen werden. Doch bevor ein endgültiges Befüllen mit Ätzlösung durchgeführt wird, bitte ich nochmals um einen anschließenden Dichtigkeitstest und Funktionscheck der fertigen Apparatur mit WASSER.&lt;br /&gt;
Der Schlauch des Luftverteilers wird über das Rückschlagventil mit der Membranpumpe verbunden und eingeschaltet. &lt;br /&gt;
Danach wird das Heizelement eingesetzt und in Betrieb genommen. Mit Hilfe eines Thermometers wird der Abschaltmoment auf ca. 50°C eingestellt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Ätzgerät_fertig.jpg|640|center|FERTIG]]&lt;br /&gt;
&lt;br /&gt;
== Volumen reduzieren == &lt;br /&gt;
Ist das geringe Volumen (0,5 Liter für die Ätzlösung)  für eure Zwecke zu groß, könnt ihr den Küvettenboden mit Glasperlen (Deko-Glaskiesel) auffüllen. &lt;br /&gt;
Diese Glasperlen verdrängen die Ätzlösung und somit kann man mit weniger Lösung arbeiten.&lt;br /&gt;
Warum nicht eine kleinere Küvette bauen oder einfach weniger Ätzlösung ansetzen?&lt;br /&gt;
Das Heizelement hat eine Mindestlänge, wenn dieses Heizelement nicht komplett mit der Heizwendel unter Wasser (Ätzlösung) steht, kann dieses zerplatzen. Durch die Glaskiesel wird gewährleistet, dass das Element komplett eintaucht aber weniger Volumen in der Küvette zur kompletten Füllung benötigt wird.&lt;br /&gt;
&lt;br /&gt;
==Tipps zur Pflege==&lt;br /&gt;
Die Ätzlösung kann auch bei Nichtgebrauch in der Küvette gelagert werden. Dann kann es jedoch vorkommen, dass sich der Sprudelschlauch mit der Zeit zusetzt. Solange die Ätzlösung noch gebrauchsfähig ist, reicht es dann diesen z.B. mit einem entgrateten Holzstab abzustreifen. Die Poren des Schlauches werden dadurch wieder frei.&lt;br /&gt;
Bevor man sein Ätzgerät mit einer frischen Lösung neu befüllt sollte man die komplette Küvette gründlich mit Spülmittel reinigen. Auch in einer Spülmaschine kann die Küvette (kopfüber) gereinigt werden (Achtung! &amp;quot;Mutti&amp;quot; fragen ;-)). Der Sprudelschlauch kann mit einem groben Schwamm von den z.T. unsichtbaren Ablagerungen gereinigt und somit wieder durchlässig gemacht werden.&lt;br /&gt;
&lt;br /&gt;
==Mögliche Ätzlösungen==&lt;br /&gt;
welche für dieses Gerät geeignet sind:&lt;br /&gt;
&lt;br /&gt;
===Ammoniumpersulfat===&lt;br /&gt;
Das Mittel wird als weißes, kristallines Pulver geliefert, sollte luftdicht gelagert werden und ist etwas umweltfreundlicher als Eisen-III-Chlorid. Es reagiert ebenfalls hygroskopisch. 500 g des Mittels reichen für 2 Liter Ätzlösung. Beim Auflösen unter Rühren kühlt sich die Lösung deutlich ab. Die frische Ätzlösung ist klar bis leicht milchig, mit zunehmendem Kupfergehalt verfärbt sie sich blau, bleibt jedoch immer durchsichtig, so dass der Ätzvorgang sehr gut kontrolliert werden kann. Die optimale Ätztemperatur beträgt ca. 40° C, sie sollte weder deutlich höher (&amp;lt;50° C) noch viel niedriger (&amp;gt;30° C) sein. Die Ätzzeit beträgt 5 bis 10 Minuten. Nach dem Ätzen die Leiterplatte sofort gut unter fließendem Wasser abspülen. Ein Ansatz ist in einem geschlossenen Glasgefäß lagerbar und mehrfach verwendbar (Aufnahme von bis zu 40 g Kupfer je Liter). Bei intensiver Blaufärbung ist die Lösung verbraucht. &lt;br /&gt;
* Nach Abkühlen bleiben blaue Kristalle zurück, die hochgiftig sind!&lt;br /&gt;
&lt;br /&gt;
===Natriumpersulfat===&lt;br /&gt;
'''Mein Mittel der Wahl'''. &lt;br /&gt;
Das als „Feinätzkristall” u.a. von Seno gehandelte Ätzmittel. Das Ätzmittel wird im Beutel für 0,5 l Ätzansatz geliefert. Es löst sich im Wasser schnell auf, kristallisiert nicht aus, ätzt mit sehr hoher Konturenschärfe und sehr geringer Unterätzung. Das Ätzen soll bei 40°C bis 50°C erfolgen. Die Ätzzeit beträgt 10 bis 20 Minuten bei frisch angesetzten Lösungen.  Nach dem Ätzen die Leiterplatte sofort gut unter fließendem Wasser abspülen. Die Lösung kann in einem offenen! Gefäß (z.B. die Ätzküvette) aufbewahrt werden. Durch die ständige Gasentwicklung könnte ein verschlossenes Gefäß bersten!&lt;br /&gt;
&lt;br /&gt;
===Absolut ungeeignete Ätzlösungen===&lt;br /&gt;
&lt;br /&gt;
* Eisen-III-Chlorid&lt;br /&gt;
Dieses fast schon historische Ätzmittel neigt stark zum Schäumen und würde aus der Küvette überquellen. Hierfür gibt es andere „Schaumätzgeräte“&lt;br /&gt;
Außerdem ist ein Begutachten der Leiterplatte und des Ätzfortschrittes durch die undurchsichtige bräunliche Lösung fast unmöglich.&lt;br /&gt;
&lt;br /&gt;
* Andere schaumbildende Mittel&lt;br /&gt;
* Stark säurehaltige Lösungen (HCL) sind wegen der Aggressivität gegenüber der Umgebung (nicht für die Ätzmaschine) auch für Mensch und Tier nicht empfehlenswert, da durch den Luftverteiler Spritzer verusacht werden, welche sich im direkten Umfeld des Gerätes ablegen.&lt;br /&gt;
&lt;br /&gt;
==Entsorgen von Ätzlösungen==&lt;br /&gt;
[[Bild:Aetzend.gif|left|Ätzend]][[Bild:Geshschaedl.gif|left|Gesundheitsschädlich]]Die Chemikalien bitte auf gar keinen Fall in das Abwasser leiten. Die in den Klärwerken eingesetzten Bakterien können auch durch geringste Mengen der Chemikalien und des darin gelösten Kupfers absterben. Es könnte also mit nur einer Ätzküvette eine kleine Kläranlage komplett &amp;quot;kippen&amp;quot; und dann kann es richtig teuer werden. Anleitungen, die immer noch im Internet verbreitet sind und welche eine unproblematische Entsorgung über das Abwasser bei entsprechender Verdünnung suggerieren, sind nach aktueller Gesetzeslage nicht mehr erlaubt!&lt;br /&gt;
&lt;br /&gt;
* Bitte die Chemikalien zur Reststoffverwertung / '''Sondermüllentsorgung''' bringen. &lt;br /&gt;
* Dies ist '''für Privatleute meist unentgeltlich''' und erspart einem viel Ärger.&lt;br /&gt;
&lt;br /&gt;
==Autor==&lt;br /&gt;
* [[Benutzer:Darwin.nuernberg|Darwin.nuernberg]] 08:40, 26. Mai 2006 (CEST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* [[:Kategorie: Leiterplattenentwicklung]]&lt;br /&gt;
* [[Ätzgerät (einfach)]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=225 Diesen (ähnlichen) Artikel als PDF aus dem RoboterNetz-Forum Downloaden]&lt;br /&gt;
*[http://www.glaserie.de/ Werkzeug zur Glasbearbeitung gibt's unter anderem hier (falls man intensiver damit arbeiten möchte)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Praxis]]&lt;br /&gt;
[[Kategorie:Projekte]]&lt;br /&gt;
[[Kategorie:Leiterplattenentwicklung]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=%C3%84tzger%C3%A4t_Bauanleitung&amp;diff=16036</id>
		<title>Ätzgerät Bauanleitung</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=%C3%84tzger%C3%A4t_Bauanleitung&amp;diff=16036"/>
				<updated>2010-03-19T19:34:25Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Heizelement */ Preisinfo aktualisiert und Leistungsangaben ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Selbstbauanleitung für ein 1–Liter-Ätzgerät ==&lt;br /&gt;
(Volumen für 0,5 l Ätzlösung)&lt;br /&gt;
&lt;br /&gt;
Für Leiterplatten im Europaformat (100mm x 160 mm)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_InAction_.jpg|640px|center]]&lt;br /&gt;
(Die Luftblasen werden im laufenden Betrieb noch feiner und kleiner)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bitte diese Anleitung zunächst komplett durchlesen, &lt;br /&gt;
bevor mit dem Nachbau und dem Materialeinkauf begonnen wird.&lt;br /&gt;
&lt;br /&gt;
== Beschreibung des verwendeten Materials ==&lt;br /&gt;
Die meisten Materialien bekommt man &lt;br /&gt;
* im Baumarkt (BayWa, Hornbach, Max Bahr, OBI Baumarkt, Praktiker, TOOM ect.pp.) &lt;br /&gt;
* Aquariumszubehör (auch in vielen OBI Märkten)&lt;br /&gt;
Ja, ihr habt richtig gelesen, genau die gleichen Materialien wie in der vorliegenden Bauanleitung bekommt man zwar im einschlägigen Elektronik-Fachmarkt, sind dort jedoch um ein Vielfaches teurer als im Aquariumzubehörhandel.&lt;br /&gt;
&lt;br /&gt;
==== Glasplatten ====&lt;br /&gt;
Sämtliche Glasplatten sollten, sofern verfügbar, eine Stärke von 5 mm haben.&lt;br /&gt;
Geringere Plattenstärken sind anfälliger für Bruch oder Risse.&lt;br /&gt;
&lt;br /&gt;
Von Kunststoffglas wie Plexi- oder Acrylglas rate ich ab, da dies matt und bei den im Ätzprozess verwendeten Temperaturen (50°C bis 80°C) brüchig wird. Außerdem lässt sich Glas (mit entsprechender Übung) besser und einfacher verarbeiten. Glas ist, entgegen verbreiteter Meinung, sehr leicht zu verarbeiten, wenn man sich an gewisse Regeln hält und etwas Übung hat. Wer den Zuschnitt von Glas scheut, kann sich beim Glaser entsprechende (fertige) Zuschnitte (aus Resten) besorgen. Die Reste dürften auch relativ günstig zu erstehen sein. Eine geschnittene (sauber gebrochene) Glasplatte hat im Gegensatz zu gesplittertem Glas keine so scharfen Kanten, jedenfalls sind diese bei weitem nicht so gefährlich. Trotzdem sollten die Kanten abgestumpft werden, außerdem begünstigt dies auch das Verkleben der Glasplatten untereinander. Hierzu reicht es meist aus die Kanten z.B. mit einem Edelkorund oder Diamantschleifstift (wie für viele Mini–Bohrmaschinen erhältlich) zu entgraten. Wer hat, darf natürlich auch seine Glasschleifmaschine (wie für Tiffany-Glastechnik) einsetzen.&lt;br /&gt;
&lt;br /&gt;
==== Luftverteiler für Umwälzung ====&lt;br /&gt;
(Aquaristik) Air Curtain. Ein poröser Schlauch, durch welchen die eingeblasene Luft über dessen gesamte Länge in kleinen Bläschen austritt. Diese Bläschen sorgen durch ihr Aufsteigen dafür, dass das Ätzbad in Bewegung kommt, um so eine gleichmäßige Temperatur über die gesamte Apparatur zu gewährleisten und das Aufheizen zu beschleunigen und zum anderen, dass die Leiterplatte schneller und gleichmäßiger geätzt wird. Andere Möglichkeiten das Ätzbad umzuwälzen, z.B. durch Umpumpen, sind für diese Anwendung finanziell nicht akzeptabel, da alle Komponenten säurefest sein müssten.&lt;br /&gt;
&lt;br /&gt;
==== Membran-Luftpumpe ====&lt;br /&gt;
(Aquaristik) diese sorgt für die benötigte Luft des Luftverteilers &lt;br /&gt;
&lt;br /&gt;
==== Rücklaufstopp (Ventil) ====&lt;br /&gt;
(Aquaristik) um zu verhindern, dass Ätzlösung über den Luftschlauch in die Luftpumpe und aus dem Gerät ausläuft ist diese geringe Investition ein absolutes Muss&lt;br /&gt;
&lt;br /&gt;
==== PVC-Luftschlauch ====&lt;br /&gt;
(Baumarkt) (Aquaristik) verbindet die Luftpumpe über das Ventil mit dem Luftverteiler.&lt;br /&gt;
&lt;br /&gt;
==== Latex Luftschlauch ====&lt;br /&gt;
(Baumarkt) (Aquaristik) aus Latex lieber als aus PVC; säurebeständiger. Schlauch aus PVC wird mit der Zeit porös. 4.99 €&lt;br /&gt;
&lt;br /&gt;
==== Heizelement ====&lt;br /&gt;
(Aquaristik/Elektronik Bedarf) sorgt für die benötigte Temperatur. Ein in einem Glaskolben wasserdicht eingebautes Heizelement mit Thermostat, welches in die Lösung eintaucht und diese erwärmt.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Wer sich aufgrund fehlender Infos oder Datenblätter nicht entscheiden kann und dennoch eine zuverlässige Heizung erstehen möchte, dem sind von mir folgende Heizungen empfohlen: &lt;br /&gt;
&lt;br /&gt;
'''Von Reichelt:''' Heizung0 (100W) € 31,65 € - Heizung1 (100W) 19,95 € - Heizung2 (150W) 23,95 €&lt;br /&gt;
&lt;br /&gt;
'''Von Conrad:''' 552020 - 62 € 32,24  - 530425 - 62 (150W) € 35,46&lt;br /&gt;
&lt;br /&gt;
(Preisinfo vom 19.03.2010)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== Silikon und Pistole für die Kartusche ====&lt;br /&gt;
(Baumarkt) Sanitärsilikon (essigvernetzt) für Glasabdichtung / Verklebung. Bitte kein Acryl oder sonstiges Fugen- oder Bausilikon verwenden, dies haftet nicht so gut, dichtet nicht wie benötigt und wird auf Dauer gesehen brüchig und undicht. &lt;br /&gt;
&lt;br /&gt;
==== Fugenhilfe ==== &lt;br /&gt;
Ein aus PVC bestehendes Fugenprofil hilft die Silikonnähte sauber zu verstreichen. Die Zeiten, in welchen man das Silikon mit dem in Spülmittel getränktem Finger verstrichen hat, sind ein für allemal vorbei. In einigen Home-Shopping-Sendern auch als „Fugi“ beworben und hat nichts mit Pilzen zu tun. &lt;br /&gt;
&lt;br /&gt;
==== Kunststoffprofile und Kunststoffplatten ====&lt;br /&gt;
(Baumarkt) Zur Erstellung der Halter für die Leiterplatten und als Montagegerüst für den Luftverteiler sowie des Heizelementes.&lt;br /&gt;
&lt;br /&gt;
== Dimensionierung ==&lt;br /&gt;
Bevor wir uns an die Materialbeschaffung machen und uns mit der Größe befassen, müssen wir einiges berücksichtigen: Breite der Glasküvette: Das Heizelement befindet sich in einem Glaskolben, welcher einen Durchmesser von mind. 20 mm hat. Somit entspricht die Breite der Glasküvette mindestens diesem Maß. Länge der Glasküvette: Die Länge der Glasküvette richtet sich nach mehreren Faktoren: &lt;br /&gt;
* Durchmesser des Heizelements + Spielraum&lt;br /&gt;
* Breite der maximalen Leiterplattenbreite (welche geätzt werden kann/soll)&lt;br /&gt;
* Breite der Halterung + Spielraum für die Leiterplatte, um diese ins Ätzbad tauchen und herausnehmen zu können.&lt;br /&gt;
* Platz für den Luftschlauch, welcher den Luftverteiler versorgt&lt;br /&gt;
Die Höhe der Glasküvette ist vom Volumen abhängig, Breite und Länge sowie Verdrängung des Heizelementes und der Halter + Abstand, damit die Luftbläschen, welche ebenfalls die Lösung verdrängen und somit den Pegel anheben und die aufsteigenden (welche auf der Oberfläche zerplatzen und daher spritzen) die Küvette nicht zum Überlaufen bringen. Für den Luftverteilschlauch (am Boden der Küvette) muss ebenfalls etwas Platz berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Prinzipielle Bestimmung der Glasküvettengröße''' &lt;br /&gt;
&lt;br /&gt;
Innenmaße&lt;br /&gt;
{|{{Blauetabelle}}&lt;br /&gt;
&lt;br /&gt;
|Breite:&lt;br /&gt;
|25mm&lt;br /&gt;
|20mm Heizelement + 5mm Spielraum &lt;br /&gt;
|-&lt;br /&gt;
|Länge:&lt;br /&gt;
|210mm	&lt;br /&gt;
|160mm Leiterplatte&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|2x 20mm für die Halter&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|10mm für den Luftschlauch&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|20mm Heizelement&lt;br /&gt;
|-&lt;br /&gt;
|Höhe:&lt;br /&gt;
|220mm&lt;br /&gt;
|Volumen / Breite / Länge = Höhe + Spielraum&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Volumen sollte 1 l betragen (1000000 mm³)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|1000000 / 210 / 25 ~ 190,5 mm + 30 mm Spielraum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Mit etwas angepassten Werten&lt;br /&gt;
(damit das Ganze etwas ansprechender aussieht):&lt;br /&gt;
{|&lt;br /&gt;
|B&lt;br /&gt;
|=&lt;br /&gt;
|25 mm&lt;br /&gt;
|-&lt;br /&gt;
|L&lt;br /&gt;
|=&lt;br /&gt;
|230 mm&lt;br /&gt;
|-&lt;br /&gt;
|H&lt;br /&gt;
|=&lt;br /&gt;
|200 mm&lt;br /&gt;
|}&lt;br /&gt;
Mit diesen Werten kann eine Europaplatine (160 mm x 100 mm) spielend „gebadet“ werden.&lt;br /&gt;
Bestimmung der Glasplattengröße.&lt;br /&gt;
Da sich Glasplatten mit einer Stärke von 5 mm und einer Breite von 25 mm nur für sehr geübte Hobbyglaser verarbeiten lassen, wähle ich eine breitere Variante, welche an den Stirnseiten verklebt wird; die verleiht der Glasküvette außerdem einen besseren Stand.&lt;br /&gt;
&lt;br /&gt;
=== Glaszuschnitte === Maße etwas abgeändert:&lt;br /&gt;
{|{{Blauetabelle}}&lt;br /&gt;
|Seitenteile:&lt;br /&gt;
| 2x&lt;br /&gt;
|Glasplatte a '''5 mm''' (Stärke) x &lt;br /&gt;
'''220 mm''' (Höhe) '''x 55 mm''' (Tiefe)&lt;br /&gt;
|-&lt;br /&gt;
|Vorder/Rückseiten:&lt;br /&gt;
| 2x&lt;br /&gt;
|Glasplatte a '''5 mm''' (Stärke) x &lt;br /&gt;
'''210 mm''' (Breite) '''x 220 mm''' (Höhe)&lt;br /&gt;
|-&lt;br /&gt;
|Fußplatte:&lt;br /&gt;
| 1x&lt;br /&gt;
|Glasplatte a '''5 mm''' (Stärke) x &lt;br /&gt;
'''220 mm''' (210 mm + 10 mm (Breite + Überhang)) '''x 55 mm''' (Tiefe)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Nachbau Schritt für Schritt ==&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Schleifen1.jpg|thumb|right|Stumpfschleifen mit einer Glasschleifmaschine]][[Bild:Bauanleitung-Ätzgerät_Schleifen2.jpg|thumb|right|Kanten mit einem Edelkorund stumpfschleifen]]&lt;br /&gt;
ACHTUNG: '''Immer mit Schutzbrille arbeiten!'''&lt;br /&gt;
&lt;br /&gt;
Besonders beim Schleifen springen feine Glassplitter herum, welche die Augen verletzen können.&lt;br /&gt;
&lt;br /&gt;
===Materialbearbeitung===&lt;br /&gt;
* 1. Die Glasplatten werden den Abmessungen entsprechend zugeschnitten (gebrochen)&lt;br /&gt;
TIPP:&lt;br /&gt;
Wer sein Glas selbst schneiden will, dem sei folgender Hinweis gegeben.&lt;br /&gt;
Die Bruchstelle wird sauberer, wenn man den Schnitt vor dem Brechen mit Wasser vernetzt.&lt;br /&gt;
Noch bessere Ergebnisse erzielt man, wenn man den Glasschneider mit Schneidöl (Kriechöl wie z.B. Balistol) tränkt. &lt;br /&gt;
&lt;br /&gt;
Es gibt sogar Glasschneider mit eingebautem Öltank, diese kosten ab € 35,- aber dies ist für nur einmaligen Gebrauch etwas zuviel. &lt;br /&gt;
&lt;br /&gt;
Einen sauberen Schnitt kann man kaum erkennen, ist die Schnittlinie hingegen deutlich sichtbar (ausgefranst,) deutet dies auf eine ungenaue Schnittführung oder einen defekten Glasschneider hin. Man kann sogar während des Anschneidens hören ob dieser gelingt oder unsauber wird (Übung ist alles). Mit unsauberen Schnittlinien wird dann auch die Bruchstelle unregelmäßig und „fransig“ oder wellig.&lt;br /&gt;
Ein gemäßigter nicht zu kräftiger Schlag auf die dem Schnitt abgewandten Seite der Platte lässt diese einreißen. Ein dünnes Hölzchen (Zahnstocher) direkt unter den Schnitt gelegt und mit den Daumen soweit wie möglich links und rechts vom Schnitt entfernt auf die Glasplatte drücken (Knack).&lt;br /&gt;
&lt;br /&gt;
* 2. Die Kanten müssen geschliffen (entgratet) werden, damit man sich nicht daran verletzen und der Silikon-Kleber besser haften kann (bessere Verbindung).&lt;br /&gt;
Dies kann, falls verfügbar, mit einem Glasschleifgerät (Diamantschleifkopf) oder mit weniger Aufwand aber ebenso effektiv, mit einer Minibohrmaschine und einem Edelkorund-Schleifstein erfolgen. &lt;br /&gt;
&lt;br /&gt;
Auch mit Korund beschichtetes Schleifpapier (Teller-Schleifgeräte) kann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verkleben der einzelnen Teile ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Verkleben1.jpg|thumb|right|Silikonauftrag]][[Bild:Bauanleitung-Ätzgerät_Verkleben2.jpg|thumb|right|Immer einen dünnen aber mit Silikon lückenlos gefüllten Spalt lassen (elastische Fuge)]][[Bild:Bauanleitung-Ätzgerät_Verkleben3.jpg|thumb|right|ungenutzte Glasplatten dienen als Abstandshalter bis das Silikon getrocknet ist]][[Bild:Bauanleitung-Ätzgerät_Verkleben6.jpg|thumb|right|Silikon auftragen]][[Bild:Bauanleitung-Ätzgerät_Verkleben5.jpg|thumb|right|Glasplatte nur leicht andrücken, wieder einen schmalen, aber mit Silikon lückenlos gefüllten Spalt lassen]]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Glasplatten werden mit Silikon verklebt. Nur essigvernetztes Sanitärsilikon verwenden, transparent oder gefärbt ist egal.&lt;br /&gt;
Acryl oder Bausilikon ist ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Um eine einwandfreie Klebestelle zu gewährleisten müssen die betroffenen Stellen absolut sauber, trocken und fettfrei sein. Auch Fingerabdrücke beeinflussen die Klebekraft.&lt;br /&gt;
Am besten die entsprechenden Stellen unmittelbar vorher mit ACETON und einem Küchenkrepp reinigen. Nagellackentferner enthält oft auch Aceton, ist aber wegen der beigemengten Öle und Pflegemittel ungeeignet.&lt;br /&gt;
„Normales“ Aceton ist im Baumarkt oder in einer Drogerie erhältlich.&lt;br /&gt;
&lt;br /&gt;
====Rückwärtiges- und Bodenteil====&lt;br /&gt;
Die ersten beiden Bauteile werden zusammengefügt.&lt;br /&gt;
&lt;br /&gt;
Nicht Platte an Platte pressen, sondern einen hauchdünnen Spalt ohne Lufteinschlüsse lassen.&lt;br /&gt;
So bleibt die Fuge elastisch und kann besser trocknen.&lt;br /&gt;
&lt;br /&gt;
Kleinere Fehlstellen ohne dichte Verklebung sind hier zunächst nicht so tragisch. Die endgültige Dichtigkeit wird am Schluss sichergestellt.&lt;br /&gt;
Hier geht es zunächst um die mechanische Stabilität. Nicht alle Bauteile auf einmal zusammenfügen, hier ist viel Geduld notwendig. Zunächst sollte die erste Verbindung aushärten, bevor man mit der nächsten weitermacht. Dies kann durchaus einen ganzen Tag dauern (je nach Silikon). Oberflächlich getrocknetes Silikon ist im Kern noch lange nicht fest, daher lieber etwas mehr Zeit verstreichen lassen als zuwenig. Im schlimmsten Falle haften die einzelne Teile nicht fest genug aneinander. Nach ca. 12h dürfte allerdings eine genügende Trocknung erreicht sein. &lt;br /&gt;
Jetzt darf diese erste Klebestelle erst einmal bis zur Festigkeit austrocknen.&lt;br /&gt;
&lt;br /&gt;
==== Frontseitiges- und Bodenteil ====&lt;br /&gt;
Ist diese erste Verklebung nun getrocknet, legt man wieder einige Reststücke von den Glasplatten oder was man sonst so findet, um die 2. Platte mit einem Abstand (25 mm) auflegen zu können. Wichtig ist, dass die Platte stabil zu liegen kommt und nicht verwackelt sowie dass die Ränder frei bleiben.&lt;br /&gt;
Diesmal sollten es aber so ziemlich genau die berechneten 25 mm sein.&lt;br /&gt;
&lt;br /&gt;
Auf diesen Abstandshalter legt man dann die zweite, mit an der eine Kante mit Silikon vorbereitete Glasplatte und bringt diese in Stellung (Kontakt mit geringem Spalt zur Bodenplatte, so dass das Silikon gut anhaftet). &lt;br /&gt;
Nicht Platte an Platte pressen, sondern einen hauchdünnen Spalt ohne Lufteinschlüsse lassen.&lt;br /&gt;
Nun wieder warten, bis die Klebestelle getrocknet ist und ihre Endfestigkeit erreicht hat &lt;br /&gt;
(über Nacht {mind. 8h} dürfte auch hier reichen, aber wie erwähnt, lieber länger warten als zu kurz).&lt;br /&gt;
&lt;br /&gt;
==== Seitenteile ====&lt;br /&gt;
Nachdem die Silikonnähte der Front- und Rückseite an der Bodenplatte wirklich Endfestigkeit haben, drehen wir diese so um 90°, dass der Aufbau auf einem Seitenteil zu stehen kommt.&lt;br /&gt;
Jetzt ist etwas mehr Sorgfalt angesagt.&lt;br /&gt;
&lt;br /&gt;
Den inneren Abstand der Küvette fixieren wir wieder mit den Teilen, welche schon zuvor den Abstand bestimmt haben. An der offenen Seite fixieren wir die Platten z.B. mit Klebeband, so dass diese nicht aus Versehen auffächern können. Somit ist über die gesamte Höhe ein gleichmäßiger Abstand gewährleistet.&lt;br /&gt;
Jetzt noch die Platten so ausrichten, dass diese im rechten Winkel zueinander stehen.&lt;br /&gt;
Auf die Kanten wird wieder das Silikon aufgetragen.&lt;br /&gt;
Hier ist es ratsam besonders in den Ecken keine „offene“ Stelle zu haben, da dies ein besonders kritischer Bereich ist.&lt;br /&gt;
&lt;br /&gt;
Jetzt wieder trocknen lassen ...&lt;br /&gt;
Danach genauso mit der gegenüberliegenden Seite verfahren.&lt;br /&gt;
&lt;br /&gt;
=== Finishing ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Finishing1.jpg|thumb|right|Finishing]] [[Bild:Bauanleitung-Ätzgerät_Dichtetest1.jpg|thumb|right|Dichte-Test mit Wasser]]&lt;br /&gt;
Das Finishing entscheidet letztendlich ob unsere Glasküvette dicht wird oder ob diese leckt.&lt;br /&gt;
Zunächst entfernen wir die herausgequollenen „Silikonwürste“ auf der Außenseite mit einem Cuttermesser. Auf der Innenseite ist dieses herausgequollene Silikon nicht störend (nur optisch). &lt;br /&gt;
* '''Achtung:''' nicht in die Fuge hineinschneiden, sondern nur das überstehende Material entfernen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Erster Dichtigkeitstest ===&lt;br /&gt;
Die Küvette mit Wasser füllen und entsprechende Stellen, an welchen Wasser austritt, &lt;br /&gt;
mit Filzstift oder Fettstift markieren. Diese Stellen müssen im letzten Schritt besonders beachtet und abgedichtet werden &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fugen mit der Fugenhilfe nacharbeiten ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Fugi1.jpg|thumb|right|Silikon-Fugenhilfe]]&lt;br /&gt;
Jetzt kommt das auch als „Fugi“ bekanntes Werkzeug zum Einsatz.&lt;br /&gt;
Natürlich muss es nicht das Original aus dem TV-Shopping sein, auch im Baumarkt bekommt man ein entsprechendes äquivalentes Werkzeug.&lt;br /&gt;
Wählt einen eurer Meinung nach einen passenden Radius an der Fugenhilfe aus.&lt;br /&gt;
Natürlich muss wieder alles trocken, sauber, staub- und fettfrei sein, sonst ist alles umsonst. &lt;br /&gt;
&lt;br /&gt;
'''Pauschal alles noch mal mit Aceton (fettlösend) reinigen'''.&lt;br /&gt;
&lt;br /&gt;
In den bereinigten Kanten an den Fugen wird nun nochmals frisches Silikon aus der Kartusche aufgetragen und mit der Fugenhilfe geformt und geglättet. &lt;br /&gt;
Nicht zu viel und nicht zu wenig Silikon auftragen und vor allem gleichmäßig. &lt;br /&gt;
Wie viel ihr verwenden müsst, bekommt ihr mit der ersten Fuge schnell heraus (Don’t Panic).&lt;br /&gt;
Nicht alle Fugen auf einmal nacharbeiten, erst die eine, dann die nächste Fuge.&lt;br /&gt;
&lt;br /&gt;
Durch die genaue Führung mit der Fugenhilfe kann „nass in nass“ gearbeitet werden, &lt;br /&gt;
d.h es muss hier nicht immer wieder gewartet werden bis alles getrocknet ist. &lt;br /&gt;
Es geht eigentlich alles fix und sehr sauber.&lt;br /&gt;
&lt;br /&gt;
=== Handhabung der Fugenhilfe ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Fugi2.jpg|thumb|right|Silikon-Fugenhilfe anwenden]]&lt;br /&gt;
Die Fugenhilfe wird so geführt, dass diese an den beiden Glasplatten anliegt um so überschüssiges Silikon abzuziehen.&lt;br /&gt;
Dabei nicht in Richtung der abgeschrägten Seite ziehen, sondern in die Richtung ziehen, zu welcher die flache Seite schaut (im Bild die abgewandte Seite).&lt;br /&gt;
In einem Zug ohne Unterbrechung das Silikon „abziehen“. &lt;br /&gt;
Ist eine Stelle mit zu wenig Silikon vorhanden einfach die betreffende Stelle mit frischem Silikon aus der Tube auffüllen und gleich noch einmal abziehen. &lt;br /&gt;
Die Fugenhilfe immer vor dem Abziehen von Silikon befreien (mit Küchenkrepp abwischen) „sonst verschmiert’s alles“&lt;br /&gt;
Übrigens: Mit Kreditkarten oder anderen Plastikkarten funktioniert dies nicht, dann lieber wieder mit dem &amp;quot;nassen Finger&amp;quot; arbeiten.&lt;br /&gt;
&lt;br /&gt;
== Ein- und Anbauarbeiten ==&lt;br /&gt;
=== Luftverteiler ===&lt;br /&gt;
Hierfür benötigen wir &lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_AirCurtain.jpg|thumb|right|AirCurtain und Rücklaufstopp-Ventil]]&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Luftverteiler_Base1.jpg|thumb|right|Halter für Luftverteiler]]&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Luftverteiler_Base2.jpg|thumb|right|Luftverteiler auf Halter fixieren]]&lt;br /&gt;
eine Sprudelquelle (Air Curtain), &lt;br /&gt;
einen PVC-Schlauch, &lt;br /&gt;
ein Rückschlagventil und &lt;br /&gt;
ein Kunststoffprofil sowie &lt;br /&gt;
etwas Silikon und&lt;br /&gt;
Frischhaltefolie.&lt;br /&gt;
Natürlich auch eine elektrische Luft- bzw. Membranpumpe.&lt;br /&gt;
&lt;br /&gt;
Um zu verhindern, dass der Sprudelschauch nach oben treibt, verankern wir diesen auf einem Kunststoffprofil und fixieren den Schlauch mit Silikon, da dies gegen die Ätzbäder resistent ist.&lt;br /&gt;
Silikon haftet aber nicht auf allen Materialien, speziell nicht auf PVC und ähnlichen Kunststoffen, so behelfen wir uns mit einem Trick:&lt;br /&gt;
Das Kunststoffprofil hat in etwa die Abmessungen der Innenfläche unserer Glasküvette, eher etwas kleiner. Dieses Kunststoffprofil bohren wir in regelmäßigen Abständen mit ca. 4 mm durch und senken diese auf der Unterseite großzügig an. Auf diese Bohrungen geben wir großzügig Silikon, so dass dieses durch die Bohrung auf der anderen Seite austritt, zusätzlich legen wir einen Silikonstrang quer zum Profil auf.&lt;br /&gt;
&lt;br /&gt;
Diese so vorbereitete Profil legen wir auf Frischhaltefolie, da diese später leicht vom getrockneten Silikon entfernt werden kann.&lt;br /&gt;
Darauf legen wir dann den vorher abgelängten „Air Curtain“-Schlauch und fixieren diesen wiederum mit Silikonsträngen. Diese „Konstruktion“ lassen wir über Nacht trocknen.&lt;br /&gt;
&lt;br /&gt;
Da das Silikon in die Senkungen gepresst wird hält dies mechanisch, sozusagen wie ein Niet oder Druckknopf, den Luftverteiler am Profil. Das an den Seiten überstehende Silikon kann nach dem Austrocknen problemlos abgeschnitten werden oder mit Hilfe der Frischhaltefolie im feuchten Zustand in die Fugen unter dem Schlauch verteilt werden. &lt;br /&gt;
&lt;br /&gt;
Das '''Silikon nicht über die gesamte Schlauchlänge verteilen''', da sonst keine Luft mehr austreten kann. Nach dem Abbinden des Silikons können die überstehenden Reste abgeschnitten werden und dann wird abschließend der PVC-Schlauch angeschlossen und dieser Luftverteiler, evtl. wieder mit etwas (sehr wenig) Silikon, am Glasküvettenboden fixiert.&lt;br /&gt;
&lt;br /&gt;
=== Heizelement ===&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Heizelement_Halter.jpg|thumb|right|Heizungshalter]]&lt;br /&gt;
Für das Heizelement benötigen wir als Halter eigentlich nur ein Stück vom Kunststoffprofil, dessen Mindestabmessungen so groß sind, damit dieses nicht in die Küvette fallen kann und Platz für eine Bohrung bietet, damit dieses über den Glaskolben des Heizelementes geschoben werden kann ohne dass dieses komplett durchrutschen kann.&lt;br /&gt;
Die abgebildete Version zeigt den Halter mit einer zusätzlichen Bohrung zur Durchführung des Luftschlauches für den Luftverteiler.&lt;br /&gt;
&lt;br /&gt;
=== Leiterplattenhalter ===&lt;br /&gt;
Der Leiterplattenhalter muss mehrere Eigenschaften besitzen.&lt;br /&gt;
* zum einen soll die Leiterplatte sicher gehalten werden,&lt;br /&gt;
* zum anderen muss die Leiterplatte auch am Rand von der Ätzlösung umspült werden können&lt;br /&gt;
* und nicht zuletzt muss der Halter an unterschiedliche Leiterplattengrößen angepasst werden können.&lt;br /&gt;
&lt;br /&gt;
Eine nahezu perfekte Lösung dieser gestellten Probleme bieten die u.a. von der Fa. ISEL auch einzeln erhältlichen Leiterplattenhalter, welche auch auf die Abmessungen unserer selbst gebauten Ätzmaschiene angepasst werden kann.&lt;br /&gt;
* '''Achtung:''' Wenn z.B. der ISEL Platinenhalter gekauft wird, reicht der Platz für eine Europaplatine (100x160mm) nicht mehr aus, da der Halter breiter ist als der hier im folgenden beschriebene Selbstbauhalter. Es können dann eben nur schmälere (max. 100x120mm) Platinen geätzt werden.&lt;br /&gt;
Aber was wäre das denn für eine Bauanleitung, wenn nicht auch alles selbst gebaut bzw. beschrieben wird? (So einfach mache ich es mir dann doch nicht.)&lt;br /&gt;
Das Problem besteht darin, eine einfache und dennoch praktikable und relativ einfach nachzubildende Konstruktion zu finden. Die entsprechenden Profile, wie von Isel verwendet, sind nicht so leicht zu beschaffen.&lt;br /&gt;
Wir benötigen folgende Materialien:	&lt;br /&gt;
	Ein quadratisches Kunststoffvollprofil mit etwa 11mm (11,5mm) Kantenlänge&lt;br /&gt;
	ein flaches Kunststoffprofil mit etwa 3mm Stärke und ca. 35mm (35,5mm) Breite&lt;br /&gt;
	ein rundes Kunststoffvollprofil mit einem Durchmesser von ca. 7mm (7,5mm)&lt;br /&gt;
	Kunststoff- oder Blechschrauben 3,5 x 20mm (Linsenkopf)&lt;br /&gt;
Die quadratischen Profile werden auf eine Länge von ca. 19 cm geschnitten, an beiden Enden mit einem Abstand von ca. 1 cm und ca. 2 cm zur Kante mit einer 8-mm-Bohrung versehen und eine Nut in das Profil von Bohrung zu Bohrung gefräst.&lt;br /&gt;
&lt;br /&gt;
==== Eingefräste Nuten ====&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Leiterplattenhalter1.jpg|thumb|right|Platinenhalter Oberteil]][[Bild:Bauanleitung-Ätzgerät_Leiterplattenhalter2.jpg|thumb|right|Platinenhalter Seitenteile]][[Bild:Bauanleitung-Ätzgerät_Leiterplattenhalter3.jpg|thumb|right|Platinenhalter komplett montiert]]Zum Fräsen kann eine Mini-Bohrmaschine in einem Bohrständer fixiert und mit einem entspr. Fräsbohrer bestückt werden. Das Kunststoffprofil wird dann entweder in einem Schraubstock, in welchem das Profil locker geführt wird oder an einem entspr. Anschlag geführt, damit die Nut auch gleichmäßig geführt wird. Natürlich kann auch ein Kreuzfrästisch benutzt werden, aber wer hat denn schon so was (außer mir natürlich) in seiner Werkstatt.&lt;br /&gt;
&lt;br /&gt;
In die Bohrungen werden die runden, entsprechend gekürzten Kunststoffvollprofile gesteckt und später auf einer Seite verklebt, damit diese nicht herausrutschen können. Diese Stangen dienen später dazu, dass sich die Leiterplattenhalter, welche sich durch die Temperatur des Ätzbades verbiegen können, nicht zu stark auseinander biegen und somit die eingeklemmte Leiterplatte verlieren. Außerdem hat die Leiterplatte hiermit einen Halt und kann nicht aus der Halterung fallen.&lt;br /&gt;
&lt;br /&gt;
==== Deckelteil ==== &lt;br /&gt;
Deckelteil wird entsprechend der verbleibenden Länge aus dem flachen Kunststoffprofil gefertigt. (Die Breite der Glasküvette, abzüglich der Breite der Halterung für das Heizelement.&lt;br /&gt;
Dann wird eine Nut eingefräst, in der dann mittels Schrauben die quadratischen Halter befestigt werden. Die Nuten sollten einen Abstand zum Rand von ca. 1 cm und untereinander einen Abstand von ca. 4 cm haben, somit hat der Deckelteil noch genügend Stabilität, um nicht auseinander zu brechen und die gesamte Aufhängung am Küvettenrand zu halten.&lt;br /&gt;
&lt;br /&gt;
==== Montage des Leiterplattenhalters ====&lt;br /&gt;
Die beiden bearbeiteten Vierkantprofile werden an einer Seite (größerer Abstand zu den Stabis) für die Schraubenaufnahme angebohrt. Mittels Schrauben werden diese am Deckelteil befestigt und die Rundstäbe durch die Bohrungen geführt. Die in die Vierkantprofile eingefrästen Nuten zeigen zueinander. Die Rundstäbe werden beide an einer Seite mit Kleber fixiert oder besser an einem Ende erhitzt und breit gedrückt (breiter als die Bohrungen im Halter).&lt;br /&gt;
&lt;br /&gt;
== Endmontage ==&lt;br /&gt;
Die fertige Ätzmaschine kann jetzt in Betrieb genommen werden. Doch bevor ein endgültiges Befüllen mit Ätzlösung durchgeführt wird, bitte ich nochmals um einen anschließenden Dichtigkeitstest und Funktionscheck der fertigen Apparatur mit WASSER.&lt;br /&gt;
Der Schlauch des Luftverteilers wird über das Rückschlagventil mit der Membranpumpe verbunden und eingeschaltet. &lt;br /&gt;
Danach wird das Heizelement eingesetzt und in Betrieb genommen. Mit Hilfe eines Thermometers wird der Abschaltmoment auf ca. 50°C eingestellt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bauanleitung-Ätzgerät_Ätzgerät_fertig.jpg|640|center|FERTIG]]&lt;br /&gt;
&lt;br /&gt;
== Volumen reduzieren == &lt;br /&gt;
Ist das geringe Volumen (0,5 Liter für die Ätzlösung)  für eure Zwecke zu groß, könnt ihr den Küvettenboden mit Glasperlen (Deko-Glaskiesel) auffüllen. &lt;br /&gt;
Diese Glasperlen verdrängen die Ätzlösung und somit kann man mit weniger Lösung arbeiten.&lt;br /&gt;
Warum nicht eine kleinere Küvette bauen oder einfach weniger Ätzlösung ansetzen?&lt;br /&gt;
Das Heizelement hat eine Mindestlänge, wenn dieses Heizelement nicht komplett mit der Heizwendel unter Wasser (Ätzlösung) steht, kann dieses zerplatzen. Durch die Glaskiesel wird gewährleistet, dass das Element komplett eintaucht aber weniger Volumen in der Küvette zur kompletten Füllung benötigt wird.&lt;br /&gt;
&lt;br /&gt;
==Tipps zur Pflege==&lt;br /&gt;
Die Ätzlösung kann auch bei Nichtgebrauch in der Küvette gelagert werden. Dann kann es jedoch vorkommen, dass sich der Sprudelschlauch mit der Zeit zusetzt. Solange die Ätzlösung noch gebrauchsfähig ist, reicht es dann diesen z.B. mit einem entgrateten Holzstab abzustreifen. Die Poren des Schlauches werden dadurch wieder frei.&lt;br /&gt;
Bevor man sein Ätzgerät mit einer frischen Lösung neu befüllt sollte man die komplette Küvette gründlich mit Spülmittel reinigen. Auch in einer Spülmaschine kann die Küvette (kopfüber) gereinigt werden (Achtung! &amp;quot;Mutti&amp;quot; fragen ;-)). Der Sprudelschlauch kann mit einem groben Schwamm von den z.T. unsichtbaren Ablagerungen gereinigt und somit wieder durchlässig gemacht werden.&lt;br /&gt;
&lt;br /&gt;
==Mögliche Ätzlösungen==&lt;br /&gt;
welche für dieses Gerät geeignet sind:&lt;br /&gt;
&lt;br /&gt;
===Ammoniumpersulfat===&lt;br /&gt;
Das Mittel wird als weißes, kristallines Pulver geliefert, sollte luftdicht gelagert werden und ist etwas umweltfreundlicher als Eisen-III-Chlorid. Es reagiert ebenfalls hygroskopisch. 500 g des Mittels reichen für 2 Liter Ätzlösung. Beim Auflösen unter Rühren kühlt sich die Lösung deutlich ab. Die frische Ätzlösung ist klar bis leicht milchig, mit zunehmendem Kupfergehalt verfärbt sie sich blau, bleibt jedoch immer durchsichtig, so dass der Ätzvorgang sehr gut kontrolliert werden kann. Die optimale Ätztemperatur beträgt ca. 40° C, sie sollte weder deutlich höher (&amp;lt;50° C) noch viel niedriger (&amp;gt;30° C) sein. Die Ätzzeit beträgt 5 bis 10 Minuten. Nach dem Ätzen die Leiterplatte sofort gut unter fließendem Wasser abspülen. Ein Ansatz ist in einem geschlossenen Glasgefäß lagerbar und mehrfach verwendbar (Aufnahme von bis zu 40 g Kupfer je Liter). Bei intensiver Blaufärbung ist die Lösung verbraucht. &lt;br /&gt;
* Nach Abkühlen bleiben blaue Kristalle zurück, die hochgiftig sind!&lt;br /&gt;
&lt;br /&gt;
===Natriumpersulfat===&lt;br /&gt;
'''Mein Mittel der Wahl'''. &lt;br /&gt;
Das als „Feinätzkristall” u.a. von Seno gehandelte Ätzmittel. Das Ätzmittel wird im Beutel für 0,5 l Ätzansatz geliefert. Es löst sich im Wasser schnell auf, kristallisiert nicht aus, ätzt mit sehr hoher Konturenschärfe und sehr geringer Unterätzung. Das Ätzen soll bei 40°C bis 50°C erfolgen. Die Ätzzeit beträgt 10 bis 20 Minuten bei frisch angesetzten Lösungen.  Nach dem Ätzen die Leiterplatte sofort gut unter fließendem Wasser abspülen. Die Lösung kann in einem offenen! Gefäß (z.B. die Ätzküvette) aufbewahrt werden. Durch die ständige Gasentwicklung könnte ein verschlossenes Gefäß bersten!&lt;br /&gt;
&lt;br /&gt;
===Absolut ungeeignete Ätzlösungen===&lt;br /&gt;
&lt;br /&gt;
* Eisen-III-Chlorid&lt;br /&gt;
Dieses fast schon historische Ätzmittel neigt stark zum Schäumen und würde aus der Küvette überquellen. Hierfür gibt es andere „Schaumätzgeräte“&lt;br /&gt;
Außerdem ist ein Begutachten der Leiterplatte und des Ätzfortschrittes durch die undurchsichtige bräunliche Lösung fast unmöglich.&lt;br /&gt;
&lt;br /&gt;
* Andere schaumbildende Mittel&lt;br /&gt;
* Stark säurehaltige Lösungen (HCL) sind wegen der Aggressivität gegenüber der Umgebung (nicht für die Ätzmaschine) auch für Mensch und Tier nicht empfehlenswert, da durch den Luftverteiler Spritzer verusacht werden, welche sich im direkten Umfeld des Gerätes ablegen.&lt;br /&gt;
&lt;br /&gt;
==Entsorgen von Ätzlösungen==&lt;br /&gt;
[[Bild:Aetzend.gif|left|Ätzend]][[Bild:Geshschaedl.gif|left|Gesundheitsschädlich]]Die Chemikalien bitte auf gar keinen Fall in das Abwasser leiten. Die in den Klärwerken eingesetzten Bakterien können auch durch geringste Mengen der Chemikalien und des darin gelösten Kupfers absterben. Es könnte also mit nur einer Ätzküvette eine kleine Kläranlage komplett &amp;quot;kippen&amp;quot; und dann kann es richtig teuer werden. Anleitungen, die immer noch im Internet verbreitet sind und welche eine unproblematische Entsorgung über das Abwasser bei entsprechender Verdünnung suggerieren, sind nach aktueller Gesetzeslage nicht mehr erlaubt!&lt;br /&gt;
&lt;br /&gt;
* Bitte die Chemikalien zur Reststoffverwertung / '''Sondermüllentsorgung''' bringen. &lt;br /&gt;
* Dies ist '''für Privatleute meist unentgeltlich''' und erspart einem viel Ärger.&lt;br /&gt;
&lt;br /&gt;
==Autor==&lt;br /&gt;
* [[Benutzer:Darwin.nuernberg|Darwin.nuernberg]] 08:40, 26. Mai 2006 (CEST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* [[:Kategorie: Leiterplattenentwicklung]]&lt;br /&gt;
* [[Ätzgerät (einfach)]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=225 Diesen (ähnlichen) Artikel als PDF aus dem RoboterNetz-Forum Downloaden]&lt;br /&gt;
*[http://www.glaserie.de/ Werkzeug zur Glasbearbeitung gibt's unter anderem hier (falls man intensiver damit arbeiten möchte)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Praxis]]&lt;br /&gt;
[[Kategorie:Projekte]]&lt;br /&gt;
[[Kategorie:Leiterplattenentwicklung]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=15981</id>
		<title>TWI Slave mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=TWI_Slave_mit_avr-gcc&amp;diff=15981"/>
				<updated>2010-02-19T17:31:17Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: überarbeitete Version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programm für einen AVR mit [[TWI]] (Hardware-[[I2C]])-Schnittstelle als Slave.&lt;br /&gt;
Manchmal stellt sich die Aufgabe, mehrere AVRs per [[I2C]] zu vernetzen. Ein Beispiel ist die Erweiterung eines bestehenden Systems um einen leistungsstärkeren Controller. Dies ist etwa beim [[Asuro]] oder [[Yeti]] denkbar, um z.B. mehr Ein/Ausgänge oder Speicherplatz zu bekommen.&lt;br /&gt;
&lt;br /&gt;
Man kann aber beim Bau eines Roboters auch von Anfang an auf ein System von mehreren vernetzten Controllern setzen. So kann man verschiedene Aufgabe, die weitgehend unabhängig voneinader gleichzeitg erledigt werden müssen, besser verteilen. Denkbar ist z.B. ein Controller für die Motorsteuerung, einer für die Sensorik, einer für Ein-und Ausgabe (wie LCD und Bedientaster),... , und ein zentraler Controller, der die Richtung vorgibt und alle anderen Controller mit Befehlen versorgt. Ein konkretes Beispiel ist der Roboterbausatz Nibo (siehe: [http://www.nicai-systems.de/nibo.html]) von nicai-systems, der einen Atmel ATmega128 als Hauptcontroller und zwei Atmel ATtiny44 als Controller für die Motorsteuerung und die IR-Sensorik einsetzt. Die Kommunikation läuft mit 400 kHz über den I2C-Bus mit dem ATmega128 als Master.&lt;br /&gt;
&lt;br /&gt;
Schließlich kann ein entsprechend programmierter AVR auch als Ersatz für handelsübliche I2C-Bauteile dienen. Der kleinste AVR mit Hardware-I2C, der ATmega48, ist mit 1,30€ (Reichelt) billiger als viele normale I2C-ICs. Er kann bei entsprechender Programmierung z.B. die Aufgaben von zwei PCF8574 (8bit-Portexpander, 1,25€) und einem PCF8591 (4fach AD-Wandler, 2,35€) übernehmen und außerdem noch als I2C-EEPROM mit 256 Bytes dienen. &lt;br /&gt;
&lt;br /&gt;
Das folgende Programm (twislave.c) steuert das TWI (Hardware-I2C)-Interface eines AVRs als Slave an. Es müsste auf allen AVRs der Mega-Reihe funktionieren, die über eine TWI-Schnittstelle verfügen. &lt;br /&gt;
&lt;br /&gt;
Das System ist als eine Art Dualport-RAM konzipiert, Master und Slave teilen sich also einen Speicherbereich und können darüber Daten austauschen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Master ==&lt;br /&gt;
Ein Codeschnipsel für den Master. Es wird die [http://homepage.hispeed.ch/peterfleury/avr-software.html#libs I2C-Master-Bibliothek von Peter Fleury] verwendet.&lt;br /&gt;
Es wird geprüft, ob der Slave bereit ist, dann werden die ersten drei Bytes aus dem txbuffer des Slaves gelesen und in byte0..2 abgespeichert.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.c&amp;quot;  //I2C-Master-Routinen von Peter Fleury verwenden (siehe http://homepage.hispeed.ch/peterfleury/avr-software.html#libs)&lt;br /&gt;
#define SLAVE_ADRESSE 0x50&lt;br /&gt;
uint8_t byte0;&lt;br /&gt;
uint8_t byte1;&lt;br /&gt;
uint8_t byte2;&lt;br /&gt;
&lt;br /&gt;
      if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?&lt;br /&gt;
      {&lt;br /&gt;
         i2c_write(0x00); //Buffer Startadresse zum Auslesen&lt;br /&gt;
         i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen&lt;br /&gt;
&lt;br /&gt;
            byte0= i2c_readAck();&lt;br /&gt;
            byte1= i2c_readAck();&lt;br /&gt;
            byte2= i2c_readNak(); //letztes Byte lesen, darum kein ACK&lt;br /&gt;
         i2c_stop();&lt;br /&gt;
      } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave sourcecode ==&lt;br /&gt;
Die twislave.c für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		//enthält z.B. die Bezeichnungen für die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur Behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		//definiert den Datentyp uint8_t&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/*Der Buffer, in dem die Daten gespeichert werden. &lt;br /&gt;
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.&lt;br /&gt;
Für den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t buffer_adr; //&amp;quot;Adressregister&amp;quot; für den Buffer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
Parameter adr: gewünschte Slave-Adresse&lt;br /&gt;
*/&lt;br /&gt;
void init_twi_slave(uint8_t adr)&lt;br /&gt;
{&lt;br /&gt;
	TWAR= adr; //Adresse setzen&lt;br /&gt;
	TWCR &amp;amp;= ~(1&amp;lt;&amp;lt;TWSTA)|(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
	TWCR|= (1&amp;lt;&amp;lt;TWEA) | (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE); 	&lt;br /&gt;
	buffer_adr=0xFF;  &lt;br /&gt;
	sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). &lt;br /&gt;
//Makros für die verwendeten Bitmuster:&lt;br /&gt;
&lt;br /&gt;
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten&lt;br /&gt;
#define TWCR_ACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
&lt;br /&gt;
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     &lt;br /&gt;
#define TWCR_NACK TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(0&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);&lt;br /&gt;
&lt;br /&gt;
//switched to the non adressed slave mode...&lt;br /&gt;
#define TWCR_RESET TWCR = (1&amp;lt;&amp;lt;TWEN)|(1&amp;lt;&amp;lt;TWIE)|(1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEA)|(0&amp;lt;&amp;lt;TWSTA)|(0&amp;lt;&amp;lt;TWSTO)|(0&amp;lt;&amp;lt;TWWC);  &lt;br /&gt;
//Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht!&lt;br /&gt;
&lt;br /&gt;
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann &lt;br /&gt;
ein Statuscode, anhand dessen die Situation festgestellt werden kann.&lt;br /&gt;
*/&lt;br /&gt;
ISR (TWI_vect)  &lt;br /&gt;
{&lt;br /&gt;
uint8_t data=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// Slave Receiver &lt;br /&gt;
&lt;br /&gt;
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert	&lt;br /&gt;
	TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden&lt;br /&gt;
	buffer_adr=0xFF; //Bufferposition ist undefiniert&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen&lt;br /&gt;
	data=TWDR; //Empfangene Daten auslesen&lt;br /&gt;
	if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen&lt;br /&gt;
		{&lt;br /&gt;
			//Kontrolle ob gewünschte Adresse im erlaubten bereich&lt;br /&gt;
			if(data&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr= data; //Bufferposition wie adressiert setzen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!&lt;br /&gt;
				}				&lt;br /&gt;
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern&lt;br /&gt;
		}&lt;br /&gt;
	else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern&lt;br /&gt;
		{&lt;br /&gt;
		&lt;br /&gt;
			if(buffer_adr&amp;lt;i2c_buffer_size)&lt;br /&gt;
				{&lt;br /&gt;
					if(!I2C_reg_Schreibschutz[buffer_adr]) //Wenn Position nicht schreibgeschützt...&lt;br /&gt;
						i2cdata[buffer_adr]=data; 			//...dann Daten in Buffer schreibe&lt;br /&gt;
						&lt;br /&gt;
						&lt;br /&gt;
				}&lt;br /&gt;
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff&lt;br /&gt;
			TWCR_ACK;	&lt;br /&gt;
		}&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Slave transmitter&lt;br /&gt;
&lt;br /&gt;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.&lt;br /&gt;
	//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!&lt;br /&gt;
	&lt;br /&gt;
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert&lt;br /&gt;
&lt;br /&gt;
	if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! &lt;br /&gt;
		{&lt;br /&gt;
			buffer_adr=0;&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	if(buffer_adr&amp;lt;i2c_buffer_size)	&lt;br /&gt;
		{&lt;br /&gt;
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden&lt;br /&gt;
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		{&lt;br /&gt;
			TWDR=0; //Kein Daten mehr im Buffer&lt;br /&gt;
		}&lt;br /&gt;
	TWCR_ACK;&lt;br /&gt;
break;&lt;br /&gt;
&lt;br /&gt;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert &lt;br /&gt;
case TW_SR_DATA_NACK: // 0x88 &lt;br /&gt;
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received&lt;br /&gt;
case TW_SR_STOP:      // 0xA0 STOP empfangen&lt;br /&gt;
default: 	&lt;br /&gt;
    TWCR_RESET;&lt;br /&gt;
break;&lt;br /&gt;
	&lt;br /&gt;
} //end.switch (TW_STATUS)&lt;br /&gt;
} //end.ISR(TWI_vect)&lt;br /&gt;
&lt;br /&gt;
////Ende von twislave.c////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slave header ==&lt;br /&gt;
Die zugehörige Headerdatei twislave.h für den Slave. Stand: 19.2.2010&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef _TWISLAVE_H&lt;br /&gt;
#define _TWISLAVE_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt; 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;  //dient zur behandlung der Interrupts&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt; 		    //definiert den Datentyp uint8_t&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** &lt;br /&gt;
 *  @defgroup twislave TWI-Slave&lt;br /&gt;
 *  @code #include &amp;quot;twislave.h&amp;quot; @endcode&lt;br /&gt;
 * &lt;br /&gt;
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.&lt;br /&gt;
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als&lt;br /&gt;
 *  Parameter aufgerufen werden.&lt;br /&gt;
 *&lt;br /&gt;
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, &lt;br /&gt;
 * auf den von Master und Slave zugegriffen werden kann. &lt;br /&gt;
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). &lt;br /&gt;
&lt;br /&gt;
 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem&lt;br /&gt;
 * normalen I2C-EEPROM.&lt;br /&gt;
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,&lt;br /&gt;
 * und dann die Daten. &lt;br /&gt;
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere&lt;br /&gt;
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die &lt;br /&gt;
 * Bufferadresse zu schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem &lt;br /&gt;
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach&lt;br /&gt;
 * einem repeated start die Daten aus. Die Bufferposition wird &lt;br /&gt;
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes&lt;br /&gt;
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu&lt;br /&gt;
 * schreiben.&lt;br /&gt;
 *&lt;br /&gt;
 * Abgefangene Fehlbedienung durch den Master:&lt;br /&gt;
 * - Lesen ueber die Grenze des txbuffers hinaus&lt;br /&gt;
 * - Schreiben ueber die Grenzen des rxbuffers hinaus&lt;br /&gt;
 * - Angabe einer ungueltigen Schreib/Lese-Adresse&lt;br /&gt;
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben&lt;br /&gt;
 * &lt;br /&gt;
 *  @author uwegw&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*@{*/&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%&lt;br /&gt;
/**@brief Groesse des Buffers in Byte (2..254) */&lt;br /&gt;
#define i2c_buffer_size I2C_REG_ANZAHL&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%&lt;br /&gt;
/**@brief Der Buffer, in dem die Daten gespeichert werden.&lt;br /&gt;
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie&lt;br /&gt;
 *  bei einem I2C-EEPROm ab.&lt;br /&gt;
 * Fuer den Slave ist es eine globale Variable&lt;br /&gt;
*/&lt;br /&gt;
volatile uint8_t i2cdata[i2c_buffer_size+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse&lt;br /&gt;
 * @param adr gewuenschte Slave-Adresse */&lt;br /&gt;
void init_twi_slave(uint8_t adr);&lt;br /&gt;
&lt;br /&gt;
//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//&lt;br /&gt;
//____________________________________________________________________________________//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen&lt;br /&gt;
#if (__GNUC__ * 100 + __GNUC_MINOR__) &amp;lt; 304&lt;br /&gt;
	#error &amp;quot;This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//Schutz vor unsinnigen Buffergroessen&lt;br /&gt;
#if (i2c_buffer_size &amp;gt; 254)&lt;br /&gt;
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (i2c_buffer_size &amp;lt; 2)&lt;br /&gt;
	#error Buffer muss mindestens zwei Byte gross sein!&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/*@}*/&lt;br /&gt;
&lt;br /&gt;
#endif //#ifdef _TWISLAVE_H&lt;br /&gt;
////Ende von twislave.h////&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slave Testprogramm ==&lt;br /&gt;
Ein Testprogramm für den Slave. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Testprogramm für die twislave.c&lt;br /&gt;
Der Buffer wird mit Werten gefüllt. Dann wird er fortlaufend über die serielle Schnittstelle ausgegeben.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;twislave.h&amp;quot;&lt;br /&gt;
#include &amp;quot;uart.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600 //Baudrate&lt;br /&gt;
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse&lt;br /&gt;
&lt;br /&gt;
//Funktion für Warteschaleifen&lt;br /&gt;
//Parameter: Wartezeit in Milisekunden&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
void warte (int loop)  //loop: wartezeit in ms &lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	for(i=0;i&amp;lt;loop;i++) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
//TWI als Slave mit Adresse slaveadr starten&lt;br /&gt;
init_twi_slave(SLAVE_ADRESSE);&lt;br /&gt;
&lt;br /&gt;
//i2cdatamit Werten füllen, die der Master auslesen und ändern kann&lt;br /&gt;
for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
	{&lt;br /&gt;
		i2cdata[i]=10+i;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Serielle Schnittstelle aktivieren&lt;br /&gt;
uart_init((UART_BAUD_SELECT((BAUD),F_CPU)));&lt;br /&gt;
uart_puts(&amp;quot;I2C-Test\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;Teste I2C-Slave mit Adresse &amp;quot;); uart_puti(SLAVE_ADRESSE);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
uart_puts(&amp;quot;\r\n&amp;quot;); //Leerzeile&lt;br /&gt;
&lt;br /&gt;
//in einer Endlosschleife den Inhalt der Buffer ausgeben&lt;br /&gt;
while(1) &lt;br /&gt;
{&lt;br /&gt;
	uart_puts(&amp;quot;i2cdata:\r\n&amp;quot;);&lt;br /&gt;
	for(uint8_t i=0;i&amp;lt;buffer_size;i++)&lt;br /&gt;
		{&lt;br /&gt;
			uart_puti(i2cdata[i]);&lt;br /&gt;
			uart_puts(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	uart_puts(&amp;quot;\r\n&amp;quot;);//leerzeile&lt;br /&gt;
warte(500);&lt;br /&gt;
} //end.while&lt;br /&gt;
} //end.main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=15751</id>
		<title>Roboterwettbewerbe</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=15751"/>
				<updated>2009-12-04T21:12:51Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: Carolo Cup und Field Robot Event ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf diese Seite werden die bekanntesten nationalen und internationalen Roboterwettbewerbe kurz vorgestellt.&lt;br /&gt;
&lt;br /&gt;
==Überblick==&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |''' Wettbewerb primär für'''||Schüler ||Studenten || Hobbyrobotiker ||1 Person || bis 5 Personen || mehr als 5 Personen &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Eurobot|Eurobot]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Carolo_Cup|Carolo Cup]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Field_Robot_Event|Field Robot Event]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#FIRST_Lego_League|First Lego Leaue]] || X ||  ||  || || X ||    &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboChallenge (findet vorerst nicht mehr statt) || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboCup_Soccer|RoboCup Soccer]] || || X ||  ||  ||  || X  &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboCup Junior || X || || || || X || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboKing|RoboKing]] || X || || || || X ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotChallenge|RobotChallenge]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotLiga|RobotLiga]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboTest|RoboTest]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#SPURT|SPURT]] || X || || ||  || X || &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ELROB|European Land Robot Trial (ELROB)]] ||  || X ||  || ||  || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#GSF_Robot_Contest|GSF Robot Contest]] ||  ||  || X ||X || X ||  &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ROBOCOM|ROBOCOM]] || X ||  ||  ||  || X ||&lt;br /&gt;
&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
==Eurobot==&lt;br /&gt;
&amp;quot;Seit 1998 ist Eurobot ein internationaler Roboterwettbewerb für Teams von Jugendlichen, Studenten und sonstigen an Robotern interessierten Menschen.&lt;br /&gt;
Eurobot findet stets in Europa statt, ist aber für alle Länder aller Kontinente zugänglich. Im Jahre 2004 nahmen insgesamt 250 Teams aus 21 Länder an diesem technisch/wissenschaftlichen Wettbewerb teil.&amp;quot; (zitiert von www.eurobot.org)&lt;br /&gt;
Aus jedem Land dürfen maximal drei Teams zu den internationalen Finalen fahren. Diese drei Mannschaften müssen sich in nationalen Vorausscheiden qualifizieren. Die Aufgabe wird jedes Jahr neu gestellt. Nur die Rahmenbedingungen bleiben gleich: Ein Match dauert nur 90 Sekunden, es ist also sowohl Schnelligkeit als auch eine intelligente Taktik und Sicherheit gefragt. Die Spielfläche ist etwa 2x3 Meter groß.&lt;br /&gt;
Eurobot findet seit 2005 jedes Jahr in einem anderen Land statt. Der Wettbewerb wird von einer großen Rahmenveranstaltung inklusive Vorträgen und vielen Attraktionen für die zahlreichen Zuschauer ergänzt.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.eurobot.org www.eurobot.org]&lt;br /&gt;
* [http://www.eurobot-deutschland.de www.eurobot-deutschland.de]&lt;br /&gt;
&lt;br /&gt;
==Carolo Cup==&lt;br /&gt;
Dieser Wettbewerb für Studenten findet an der TU Braunschweig statt. &lt;br /&gt;
Es treten autonome Modellfahrzeuge im Maßstab 1:10 gegeneinander an. Aufgaben sind das Fahren auf einem Rundkurs (dabei muss die Fahrbahnmarkierung z.B. mit Kameras erkannt werden) und das seitliche Einparken in einer vorgegebenen Parklücke.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.carolo-cup.de www.carolo-cup.de]&lt;br /&gt;
&lt;br /&gt;
==Field Robot Event==&lt;br /&gt;
Dieser Wettbewerb für Studenten findet auf einem Maisfeld statt. Die Roboter müssen den Maisreihen folgen und &amp;quot;Unkraut&amp;quot; erkennen, wobei es mehrere Schwierigkeitsgrade gibt (z.B. können einzelne Pflanzen fehlen, oder es gibt größere Unebenheiten im Boden).&lt;br /&gt;
Der Veranstaltungsort wechselt jährlich, für 2010 ist es die TU Braunschweig.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.fieldrobotevent2010.de/ www.fieldrobotevent2010.de]&lt;br /&gt;
&lt;br /&gt;
==FIRST Lego League==&lt;br /&gt;
Bei der First Lego League handelt es sich um einen Wettbewerb der von den Firmen Lego und FIRST veranstalltet wird. Er findet jährlich auf der ganzen Welt mit regional Runden statt. Hierzu werden jedes Jahr an interressierte Gruppen die Aufgaben, wie die dafür benötigten Aufbauten aus Lego verschickt. &lt;br /&gt;
Bei diesem Wettbewerb dürfen nur Roboter eingesetzt werden, die aus dem LEGO Mindstorms System bestehen. Der Wettbewerb richtet sich vornehmlich an junge Schüler, wie auch das gesamte Mindstorms System. Deshalb dürfen die Teilnehmer auch maximal 16 Jahre alt sein. Jedes Team benötigt einen Volljährigen Coach, der dem Team bei der Bewältigung der Aufgaben hilft.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.firstlegoleague.org/ www.firstlegoleague.org]&lt;br /&gt;
&lt;br /&gt;
==RoboCup Soccer==&lt;br /&gt;
Die Komplexität und Beliebtheit von Fußball (soccer) spielten wesentliche Rollen bei der Motivation der ersten RoboCupspiele Mitte der 90er Jahre. Die Dynamik und die Komplexität von Fußball birgt enorme Herausforderungen für Wissenschaftler, die sich mit der Entwicklung von autonomen Robotern in diesem Bereich beschäftigen: &lt;br /&gt;
&lt;br /&gt;
Individuelle Herausforderungen: jeder Agent/Roboter muss Objekte erkennen, sich selbst lokalisieren, navigieren und den Ball bewegen können. Zu klären sind Fragen wie: was ist in diesem Moment wichtig in meiner Wahrnehmung? Ist meine Position und die der anderen Mitspieler bekannt? &lt;br /&gt;
Kooperation von Agenten: in einer dynamischen Echtzeitumgebung kommt es nicht auf einen einzelnen Spieler an, sondern besonders auf das kooperative Spiel, bei dem auch die Kommunikation eine große Rolle spielt.&lt;br /&gt;
&lt;br /&gt;
Dynamische Echtzeitumgebung mit sich bewegenden Objekten, von denen einige intelligente Agenten sind, die gegen einen spielen. Diese Art von Umgebung ist z.B. auch im Straßenverkehr zu beobachten, wobei die anderen Verkehrsteilnehmer zwar keine Gegner sind, die meine Pläne durchkreuzen wollen, wo aber die Situationen beliebig komplex werden können.&lt;br /&gt;
RoboCupSoccer besteht aus fünf Ligen: der Simulationsliga, der Small-Size Liga, der Middle-Size Liga, der Sony Legged Liga, und der Humanoidliga. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robocup.org www.robocup.org]&lt;br /&gt;
&lt;br /&gt;
==RoboKing==&lt;br /&gt;
RoboKing ist ein Wettbewerb für technikinteressierte Schüler, der jährlich von der TU Chemnitz organisiert wird. Jedes Team besteht aus 3 bis 5 Schülern und einem erwachsenem Teamleiter. RoboKing richtet sich ausdrücklich auch an Schülergruppen ohne große Vorkenntnisse. Ziel der Initiative ist, Schüler für ein Studium ingenieurwissenschaftlicher Fächer zu begeistern und zu zeigen, dass auch Schulfächer wie Physik und Informatik eine Menge Spaß machen können. Das Durchschnittsalter der Teilnehmer liegt bei etwa 16 Jahren. Die jüngsten Teilnehmer waren 10 Jahre alt. &lt;br /&gt;
&lt;br /&gt;
Besonderes Highlight des Wettberwebs RoboKing ist zweifellos eine Gutschrift, von denen die Teilnehmer alle Materialien die zum Bau des Roboters benötigt werden, bezahlen können. Dadurch unterscheidet sich dieser Wettbewerb von allen vergleichbaren, denn auf die teilnehmenden Schüler kommen keine Kosten für Material zu. Jedes Jahr werden 25 Teams mit dieser Gutschrift finanziell unterstützt. Ab dem Wettbewerb RoboKing 2007 (startet im Frühjahr 2006) können zusätzlich auch alle Teams teilnehmen, die sich selbst finanzieren.&lt;br /&gt;
&lt;br /&gt;
Die Endrunde des Wettbewerbs wurde 2004 und auf der Hannover Messe ausgetragen. 2006 fand das Finale auf der digital living / CeBIT statt.&lt;br /&gt;
Eine weitere Besonderheit des Wettbewerbs: Jedes Jahr müssen die Teilnehmer eine andere Aufgabenstellung lösen.  Bei den vergangenen Wettbewerben mussten die Roboter sicher durch ein großes Labyrinth navigieren, Tennisbälle einsammeln und in die eigene Basis bringen oder Bauklötzchen durch einen Hindernisparcours mit Graben, Brücke und Schlucht transportieren. Die Teilnehmer haben nach Bekanntgabe der Spielregeln etwa 8 Monate Zeit, die Aufgabe zu lösen.&lt;br /&gt;
&lt;br /&gt;
RoboKing finanziert sich ausschließlich über Spenden von zahlreichen Sponsoren. Verantwortlich für die Organisation sind die Mitarbeiter und Studenten der Professur Prozessautomatisierung der TU Chemnitz.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.roboking.de www.roboking.de]&lt;br /&gt;
&lt;br /&gt;
==RobotChallenge==&lt;br /&gt;
Die RobotChallenge ist ein österreichischer Wettbewerb für selbstgebaute, autonome Roboter, dessen Ziel es ist für den kreativen Umgang mit innovativen Technologien zu begeistern. Experimente und praktische Erfahrungen lassen Teilnehmer und Zuschauer Wissenschaft hautnah erleben. Dieser Wettbewerb soll zeigen, wie man mit einfachen Mitteln, aber offenem Geiste und Phantasie spannende, zukunftstaugliche Lösungen finden kann. &lt;br /&gt;
Folgende Disiplienen wurden dort schon ausgetragen:&lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom'''&amp;lt;br&amp;gt;&lt;br /&gt;
Möglichst schnell muss einer schwarzen Linie auf weißem Untergrund entlang gefahren werden. Reglement im Wesentlichen wie bei RC'05. &lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom Enhanced'''&amp;lt;br&amp;gt;&lt;br /&gt;
Wie Parallel-Slalom, jedoch mit Erschwernissen: ein Tunnel, eine kurze Unterbrechung der Linie und ein Hindernis auf der Linie, das umfahren werden muss. &lt;br /&gt;
&lt;br /&gt;
'''Robot-Sumo'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter treten gegeneinander an und versuchen den jeweils anderen von einer runden Platte zu schieben. Die Platte ist schwarz, der Rand ist durch einen weissen Streifen markiert. Die Regeln entsprechen der internationalen Norm für autonomes Roboter-Sumo. &lt;br /&gt;
&lt;br /&gt;
'''Hindernislauf'''&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Infrarot-Leuchtturm mit definiertem Signal am Ende des Parcours ist möglichst rasch zu erreichen. Auf dem Weg befindliche Hindernisse müssen umfahren werden. Jedes Team kann alternativ auch einen eigenen Leuchtturm als Orientierungshilfe mitbringen. Reglement im Wesentlichen wie bei RC'05, jedoch sind auch komplexere Hindernisse (z.B. Sackgassen) möglich. &lt;br /&gt;
&lt;br /&gt;
'''Puck Collect'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter - von denen einem die Farbe rot, dem anderen blau zugeteilt wird - treten gegeneinander an. Auf dem Spielfeld sind kleine rote und blaue Scheiben (Pucks) verteilt. Ziel ist es, möglichst schnell alle Pucks der eigenen Farbe einzusammeln und zur eigenen, farblich gekennzeichneten Homebase zu bringen. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotchallenge.at/ RobotChallenge]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==RobotLiga==&lt;br /&gt;
Die RobotLiga findet in Kaiserslautern statt. Der nächste Termin ist noch nicht bekannt. Teilnehmen können alle interessierten Roboterbastler.&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 75cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotliga.de/ RobotLiga]&lt;br /&gt;
&lt;br /&gt;
==RoboTest==&lt;br /&gt;
Veranstaltungsort: Bei Frankfurt am Main&lt;br /&gt;
&lt;br /&gt;
Nächster Termin: voraussichtlich im Herbst 2009&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2 bis 3cm breit. Es starten immer zwei Roboter gleichzeitig in einem Parallelslalom. Der Wettbewerb läuft in mehreren Runden nach dem KO-System. &lt;br /&gt;
&lt;br /&gt;
'''BLOCKED LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Auf der Strecke stehen Hindernisse, die umfahren werden müssen. &lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2 bis 5cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, innerhalb von drei Minuten möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MICRO LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen für sehr kleine Roboter. Die maximale Größe liegt bei 8x8x8cm und 200g. Je kleiner und leichter der Roboter ist, desto mehr Bonuspunkte gibt es.  &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''JUST WALK'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 1m zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://WWW.ROBOTEST.DE/ RoboTest]&lt;br /&gt;
&lt;br /&gt;
==SPURT==&lt;br /&gt;
Der Wettbewerb SPURT (die Abkürzung steht für &amp;quot;Schüler-Projekte um Roboter-Technik&amp;quot;) wird jährlich von der Universität Rostock veranstaltet. SPURT richtet sich an technikinteressierte Schüler. Die zu lösende Aufgabe ist eine Linienverfolgung. Wer am schnellsten die herzförmige Linie abfährt, hat gewonnen.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://spurt.uni-rostock.de/ Wettbewerb SPURT]&lt;br /&gt;
&lt;br /&gt;
==ELROB==&lt;br /&gt;
Die deutsche Bundeswehr möchte Firma und Privatpersonen einladen, am European Land-Robot Trial 2006 (ELROB 2006) teilzunehmen.  Die ELROB wird veranstaltet, um einen Überblick über den europäischen State-of-the-art auf dem Gebiet von UGVs (unmanned ground vehicles) mit Fokus auf kurzfristig realisierbare Robotersystemen zu liefern.  Hinsichtlich der vorhandenen Fähigkeiten versuchen die Organisatoren, technische Lösungen zu fördern, die den Betrieb unbemannter Fahrzeuge (UGV) verbessern.  Repräsentanten aus Militär, Grenzschutz, Spezialkräften, Polizei, Feuerwehr, und Zivilschutzagenturen aus vielen europäischen Ländern werden anwesend sein.  Die ELROB wird von einer Ausstellung begleitet, welche eine breite Vielzahl an Robotikaspekten umfasst.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.elrob2006.org/ Wettbewerb ELROB 2006]&lt;br /&gt;
&lt;br /&gt;
==GSF Robot Contest==&lt;br /&gt;
Ein neuer Wettbewerb für Hobbyrobotiker. Er findet am 19.5.07 erstmals statt. Austragunsordt ist Fröndenberg (Raum Dortmund/Unna).&lt;br /&gt;
Die Aufgaben sind teilweise angelehnt an die der RobotLiga.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegenrische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Naqch einem akustischen &amp;quot;Feueralarm&amp;quot; muss eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude gefunden und gelöscht werden. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinader an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 100cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREESTYLE'''&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Disziplin hat jeder Teilnehmer die Möglichkeit seinen Roboter vorzustellen und zu zeigen was dieser kann.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www.gsf-robot-contest.de/&lt;br /&gt;
&lt;br /&gt;
==ROBOCOM==&lt;br /&gt;
Bei diesem Wettbewerb soll eine vorgegebene Aufgabe mit LEGO MINDSTORMS NXT Robotern autonom, d.h. ohne Eingriffe von außen bewältigt werden. Mit diesem Wettbewerb möchte die Fachhochschule Gelsenkirchen in den Schulen den Einsatz moderner Techniken fördern und Schülerinnen und Schüler für ein naturwissenschaftliches Studium interessieren.&amp;lt;br&amp;gt;&lt;br /&gt;
Am 15.06.2007 fand der Schülerwettbewerb ROBOCOM2007 zum erstem Mal statt. Am 26.06.2009 veranstaltet die Fachhochschule Gelsenkirchen die ROBOCOM2009.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www2.fh-gelsenkirchen.de/FH-Sites/FB1/index.php?id=791&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Praxis]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=15750</id>
		<title>Roboterwettbewerbe</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=15750"/>
				<updated>2009-12-04T20:54:35Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Überblick */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf diese Seite werden die bekanntesten nationalen und internationalen Roboterwettbewerbe kurz vorgestellt.&lt;br /&gt;
&lt;br /&gt;
==Überblick==&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |''' Wettbewerb primär für'''||Schüler ||Studenten || Hobbyrobotiker ||1 Person || bis 5 Personen || mehr als 5 Personen &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Eurobot|Eurobot]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Carolo_Cup|Carolo Cup]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Field_Robot_Event|Field Robot Event]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#FIRST_Lego_League|First Lego Leaue]] || X ||  ||  || || X ||    &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboChallenge (findet vorerst nicht mehr statt) || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboCup_Soccer|RoboCup Soccer]] || || X ||  ||  ||  || X  &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboCup Junior || X || || || || X || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboKing|RoboKing]] || X || || || || X ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotChallenge|RobotChallenge]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotLiga|RobotLiga]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboTest|RoboTest]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#SPURT|SPURT]] || X || || ||  || X || &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ELROB|European Land Robot Trial (ELROB)]] ||  || X ||  || ||  || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#GSF_Robot_Contest|GSF Robot Contest]] ||  ||  || X ||X || X ||  &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ROBOCOM|ROBOCOM]] || X ||  ||  ||  || X ||&lt;br /&gt;
&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
==Eurobot==&lt;br /&gt;
&amp;quot;Seit 1998 ist Eurobot ein internationaler Roboterwettbewerb für Teams von Jugendlichen, Studenten und sonstigen an Robotern interessierten Menschen.&lt;br /&gt;
Eurobot findet stets in Europa statt, ist aber für alle Länder aller Kontinente zugänglich. Im Jahre 2004 nahmen insgesamt 250 Teams aus 21 Länder an diesem technisch/wissenschaftlichen Wettbewerb teil.&amp;quot; (zitiert von www.eurobot.org)&lt;br /&gt;
Aus jedem Land dürfen maximal drei Teams zu den internationalen Finalen fahren. Diese drei Mannschaften müssen sich in nationalen Vorausscheiden qualifizieren. Die Aufgabe wird jedes Jahr neu gestellt. Nur die Rahmenbedingungen bleiben gleich: Ein Match dauert nur 90 Sekunden, es ist also sowohl Schnelligkeit als auch eine intelligente Taktik und Sicherheit gefragt. Die Spielfläche ist etwa 2x3 Meter groß.&lt;br /&gt;
Eurobot findet seit 2005 jedes Jahr in einem anderen Land statt. Der Wettbewerb wird von einer großen Rahmenveranstaltung inklusive Vorträgen und vielen Attraktionen für die zahlreichen Zuschauer ergänzt.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.eurobot.org www.eurobot.org]&lt;br /&gt;
* [http://www.eurobot-deutschland.de www.eurobot-deutschland.de]&lt;br /&gt;
&lt;br /&gt;
==FIRST Lego League==&lt;br /&gt;
Bei der First Lego League handelt es sich um einen Wettbewerb der von den Firmen Lego und FIRST veranstalltet wird. Er findet jährlich auf der ganzen Welt mit regional Runden statt. Hierzu werden jedes Jahr an interressierte Gruppen die Aufgaben, wie die dafür benötigten Aufbauten aus Lego verschickt. &lt;br /&gt;
Bei diesem Wettbewerb dürfen nur Roboter eingesetzt werden, die aus dem LEGO Mindstorms System bestehen. Der Wettbewerb richtet sich vornehmlich an junge Schüler, wie auch das gesamte Mindstorms System. Deshalb dürfen die Teilnehmer auch maximal 16 Jahre alt sein. Jedes Team benötigt einen Volljährigen Coach, der dem Team bei der Bewältigung der Aufgaben hilft.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.firstlegoleague.org/ www.firstlegoleague.org]&lt;br /&gt;
&lt;br /&gt;
==RoboCup Soccer==&lt;br /&gt;
Die Komplexität und Beliebtheit von Fußball (soccer) spielten wesentliche Rollen bei der Motivation der ersten RoboCupspiele Mitte der 90er Jahre. Die Dynamik und die Komplexität von Fußball birgt enorme Herausforderungen für Wissenschaftler, die sich mit der Entwicklung von autonomen Robotern in diesem Bereich beschäftigen: &lt;br /&gt;
&lt;br /&gt;
Individuelle Herausforderungen: jeder Agent/Roboter muss Objekte erkennen, sich selbst lokalisieren, navigieren und den Ball bewegen können. Zu klären sind Fragen wie: was ist in diesem Moment wichtig in meiner Wahrnehmung? Ist meine Position und die der anderen Mitspieler bekannt? &lt;br /&gt;
Kooperation von Agenten: in einer dynamischen Echtzeitumgebung kommt es nicht auf einen einzelnen Spieler an, sondern besonders auf das kooperative Spiel, bei dem auch die Kommunikation eine große Rolle spielt.&lt;br /&gt;
&lt;br /&gt;
Dynamische Echtzeitumgebung mit sich bewegenden Objekten, von denen einige intelligente Agenten sind, die gegen einen spielen. Diese Art von Umgebung ist z.B. auch im Straßenverkehr zu beobachten, wobei die anderen Verkehrsteilnehmer zwar keine Gegner sind, die meine Pläne durchkreuzen wollen, wo aber die Situationen beliebig komplex werden können.&lt;br /&gt;
RoboCupSoccer besteht aus fünf Ligen: der Simulationsliga, der Small-Size Liga, der Middle-Size Liga, der Sony Legged Liga, und der Humanoidliga. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robocup.org www.robocup.org]&lt;br /&gt;
&lt;br /&gt;
==RoboKing==&lt;br /&gt;
RoboKing ist ein Wettbewerb für technikinteressierte Schüler, der jährlich von der TU Chemnitz organisiert wird. Jedes Team besteht aus 3 bis 5 Schülern und einem erwachsenem Teamleiter. RoboKing richtet sich ausdrücklich auch an Schülergruppen ohne große Vorkenntnisse. Ziel der Initiative ist, Schüler für ein Studium ingenieurwissenschaftlicher Fächer zu begeistern und zu zeigen, dass auch Schulfächer wie Physik und Informatik eine Menge Spaß machen können. Das Durchschnittsalter der Teilnehmer liegt bei etwa 16 Jahren. Die jüngsten Teilnehmer waren 10 Jahre alt. &lt;br /&gt;
&lt;br /&gt;
Besonderes Highlight des Wettberwebs RoboKing ist zweifellos eine Gutschrift, von denen die Teilnehmer alle Materialien die zum Bau des Roboters benötigt werden, bezahlen können. Dadurch unterscheidet sich dieser Wettbewerb von allen vergleichbaren, denn auf die teilnehmenden Schüler kommen keine Kosten für Material zu. Jedes Jahr werden 25 Teams mit dieser Gutschrift finanziell unterstützt. Ab dem Wettbewerb RoboKing 2007 (startet im Frühjahr 2006) können zusätzlich auch alle Teams teilnehmen, die sich selbst finanzieren.&lt;br /&gt;
&lt;br /&gt;
Die Endrunde des Wettbewerbs wurde 2004 und auf der Hannover Messe ausgetragen. 2006 fand das Finale auf der digital living / CeBIT statt.&lt;br /&gt;
Eine weitere Besonderheit des Wettbewerbs: Jedes Jahr müssen die Teilnehmer eine andere Aufgabenstellung lösen.  Bei den vergangenen Wettbewerben mussten die Roboter sicher durch ein großes Labyrinth navigieren, Tennisbälle einsammeln und in die eigene Basis bringen oder Bauklötzchen durch einen Hindernisparcours mit Graben, Brücke und Schlucht transportieren. Die Teilnehmer haben nach Bekanntgabe der Spielregeln etwa 8 Monate Zeit, die Aufgabe zu lösen.&lt;br /&gt;
&lt;br /&gt;
RoboKing finanziert sich ausschließlich über Spenden von zahlreichen Sponsoren. Verantwortlich für die Organisation sind die Mitarbeiter und Studenten der Professur Prozessautomatisierung der TU Chemnitz.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.roboking.de www.roboking.de]&lt;br /&gt;
&lt;br /&gt;
==RobotChallenge==&lt;br /&gt;
Die RobotChallenge ist ein österreichischer Wettbewerb für selbstgebaute, autonome Roboter, dessen Ziel es ist für den kreativen Umgang mit innovativen Technologien zu begeistern. Experimente und praktische Erfahrungen lassen Teilnehmer und Zuschauer Wissenschaft hautnah erleben. Dieser Wettbewerb soll zeigen, wie man mit einfachen Mitteln, aber offenem Geiste und Phantasie spannende, zukunftstaugliche Lösungen finden kann. &lt;br /&gt;
Folgende Disiplienen wurden dort schon ausgetragen:&lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom'''&amp;lt;br&amp;gt;&lt;br /&gt;
Möglichst schnell muss einer schwarzen Linie auf weißem Untergrund entlang gefahren werden. Reglement im Wesentlichen wie bei RC'05. &lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom Enhanced'''&amp;lt;br&amp;gt;&lt;br /&gt;
Wie Parallel-Slalom, jedoch mit Erschwernissen: ein Tunnel, eine kurze Unterbrechung der Linie und ein Hindernis auf der Linie, das umfahren werden muss. &lt;br /&gt;
&lt;br /&gt;
'''Robot-Sumo'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter treten gegeneinander an und versuchen den jeweils anderen von einer runden Platte zu schieben. Die Platte ist schwarz, der Rand ist durch einen weissen Streifen markiert. Die Regeln entsprechen der internationalen Norm für autonomes Roboter-Sumo. &lt;br /&gt;
&lt;br /&gt;
'''Hindernislauf'''&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Infrarot-Leuchtturm mit definiertem Signal am Ende des Parcours ist möglichst rasch zu erreichen. Auf dem Weg befindliche Hindernisse müssen umfahren werden. Jedes Team kann alternativ auch einen eigenen Leuchtturm als Orientierungshilfe mitbringen. Reglement im Wesentlichen wie bei RC'05, jedoch sind auch komplexere Hindernisse (z.B. Sackgassen) möglich. &lt;br /&gt;
&lt;br /&gt;
'''Puck Collect'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter - von denen einem die Farbe rot, dem anderen blau zugeteilt wird - treten gegeneinander an. Auf dem Spielfeld sind kleine rote und blaue Scheiben (Pucks) verteilt. Ziel ist es, möglichst schnell alle Pucks der eigenen Farbe einzusammeln und zur eigenen, farblich gekennzeichneten Homebase zu bringen. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotchallenge.at/ RobotChallenge]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==RobotLiga==&lt;br /&gt;
Die RobotLiga findet in Kaiserslautern statt. Der nächste Termin ist noch nicht bekannt. Teilnehmen können alle interessierten Roboterbastler.&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 75cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotliga.de/ RobotLiga]&lt;br /&gt;
&lt;br /&gt;
==RoboTest==&lt;br /&gt;
Veranstaltungsort: Bei Frankfurt am Main&lt;br /&gt;
&lt;br /&gt;
Nächster Termin: voraussichtlich im Herbst 2009&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2 bis 3cm breit. Es starten immer zwei Roboter gleichzeitig in einem Parallelslalom. Der Wettbewerb läuft in mehreren Runden nach dem KO-System. &lt;br /&gt;
&lt;br /&gt;
'''BLOCKED LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Auf der Strecke stehen Hindernisse, die umfahren werden müssen. &lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2 bis 5cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, innerhalb von drei Minuten möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MICRO LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen für sehr kleine Roboter. Die maximale Größe liegt bei 8x8x8cm und 200g. Je kleiner und leichter der Roboter ist, desto mehr Bonuspunkte gibt es.  &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''JUST WALK'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 1m zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://WWW.ROBOTEST.DE/ RoboTest]&lt;br /&gt;
&lt;br /&gt;
==SPURT==&lt;br /&gt;
Der Wettbewerb SPURT (die Abkürzung steht für &amp;quot;Schüler-Projekte um Roboter-Technik&amp;quot;) wird jährlich von der Universität Rostock veranstaltet. SPURT richtet sich an technikinteressierte Schüler. Die zu lösende Aufgabe ist eine Linienverfolgung. Wer am schnellsten die herzförmige Linie abfährt, hat gewonnen.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://spurt.uni-rostock.de/ Wettbewerb SPURT]&lt;br /&gt;
&lt;br /&gt;
==ELROB==&lt;br /&gt;
Die deutsche Bundeswehr möchte Firma und Privatpersonen einladen, am European Land-Robot Trial 2006 (ELROB 2006) teilzunehmen.  Die ELROB wird veranstaltet, um einen Überblick über den europäischen State-of-the-art auf dem Gebiet von UGVs (unmanned ground vehicles) mit Fokus auf kurzfristig realisierbare Robotersystemen zu liefern.  Hinsichtlich der vorhandenen Fähigkeiten versuchen die Organisatoren, technische Lösungen zu fördern, die den Betrieb unbemannter Fahrzeuge (UGV) verbessern.  Repräsentanten aus Militär, Grenzschutz, Spezialkräften, Polizei, Feuerwehr, und Zivilschutzagenturen aus vielen europäischen Ländern werden anwesend sein.  Die ELROB wird von einer Ausstellung begleitet, welche eine breite Vielzahl an Robotikaspekten umfasst.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.elrob2006.org/ Wettbewerb ELROB 2006]&lt;br /&gt;
&lt;br /&gt;
==GSF Robot Contest==&lt;br /&gt;
Ein neuer Wettbewerb für Hobbyrobotiker. Er findet am 19.5.07 erstmals statt. Austragunsordt ist Fröndenberg (Raum Dortmund/Unna).&lt;br /&gt;
Die Aufgaben sind teilweise angelehnt an die der RobotLiga.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegenrische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Naqch einem akustischen &amp;quot;Feueralarm&amp;quot; muss eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude gefunden und gelöscht werden. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinader an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 100cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREESTYLE'''&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Disziplin hat jeder Teilnehmer die Möglichkeit seinen Roboter vorzustellen und zu zeigen was dieser kann.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www.gsf-robot-contest.de/&lt;br /&gt;
&lt;br /&gt;
==ROBOCOM==&lt;br /&gt;
Bei diesem Wettbewerb soll eine vorgegebene Aufgabe mit LEGO MINDSTORMS NXT Robotern autonom, d.h. ohne Eingriffe von außen bewältigt werden. Mit diesem Wettbewerb möchte die Fachhochschule Gelsenkirchen in den Schulen den Einsatz moderner Techniken fördern und Schülerinnen und Schüler für ein naturwissenschaftliches Studium interessieren.&amp;lt;br&amp;gt;&lt;br /&gt;
Am 15.06.2007 fand der Schülerwettbewerb ROBOCOM2007 zum erstem Mal statt. Am 26.06.2009 veranstaltet die Fachhochschule Gelsenkirchen die ROBOCOM2009.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www2.fh-gelsenkirchen.de/FH-Sites/FB1/index.php?id=791&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Praxis]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Sensorarten&amp;diff=15002</id>
		<title>Sensorarten</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Sensorarten&amp;diff=15002"/>
				<updated>2009-06-14T20:45:49Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* SRF10 Ultraschallsensor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Welche Sensorarten gibt es==&lt;br /&gt;
Damit sich ein Roboter in seiner Umgebung bewegen kann, ohne an Hindernisse anzustoßen, und damit er ein Ziel finden und ansteuern kann, muß er irgendwie seine Umwelt &amp;quot;wahrnehmen&amp;quot;. &lt;br /&gt;
Hauptanwendung für diese Informationen aus der Umwelt ist die [[Navigation]].&lt;br /&gt;
Auf dieser Seite werden die wichtigsten Sensorarten und damit es praktischer wird auch zugleich die populärsten Robotik- und Modellbau-Sensortypen vorgestellt. Auch die Pinbelegung und Anschlussmöglichkeiten dieser Sensoren werden kurz erläutert.&lt;br /&gt;
&lt;br /&gt;
==Bumpers==&lt;br /&gt;
Als Bumpers bezeichnet man eine Art Stoßstange, die einen Mikro-Switch auslöst. &lt;br /&gt;
&lt;br /&gt;
[[Bild:microschalter.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Die Auswertung erfolgt am besten digital an einem Pin mit Pull-up Widerstand. Man kann den Eingang pollen (abfragen), aber auch einen Interrupt auslösen lassen. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Whiskers (Fühler)==&lt;br /&gt;
Das sind flexible Kunststoff-Streifen von ca. 10 cm Länge, eigentlich für Datenhandschuhe vorgesehen. Aber man kann sie auch als Fühler einsetzen, und daher auch für die Kollisions-Sensorik verwenden. Beim Verbiegen steigt der Widerstand an.  &lt;br /&gt;
&lt;br /&gt;
[[Bild:flexs_200.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Um zu messen, wird mit einem zweiten Widerstand ein Spannungsteiler aufgebaut, der dann mit einem Analog-Eingang einen Grad der Verbiegung erkennen läßt. Sie werden häufig auch Flexsensoren genannt. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Incremental-Geber==&lt;br /&gt;
Dienen zur Erfassung von Drehzahl bzw. der Messung von Wegstrecken&lt;br /&gt;
&lt;br /&gt;
===austriamicrosystems AS5040===&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Bild:AMS-general_200x200.jpg|right]]&lt;br /&gt;
[[Bild:AMS-chip_109x104.jpg|left]]&lt;br /&gt;
&lt;br /&gt;
Der AS5040 kann absolute Winkelpositionen an einer Achse messen. Die Messung wird indirekt über ein Magnetfeld mittels Hallsensoren durchgeführt. Aufgrund der Anordnung der Hallsensoren und der Integration der Sensoren direkt in Silizium wird eine sehr hohe Genauigkeit bei der Messung erreicht. Das Messprinzip kompensiert ausserdem Störgrössen, wie externes Magnetfeld, Alterungseinflüsse, Temperaturschwankungen und mechanische Toleranzen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Die komplette Auswertung der Sensorsignale geschieht auf dem Chip. &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:AMS-block_700x242.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:AMS-pcb_200x152.jpg|right]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Durch die hohe Integration reduziert sich die zusätzliche Beschaltung des Chips auf wenige Bauteile, beispielsweise ein paar Filterkondensatoren. &lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Die Winkelencoderfamilie von austriamicrosystems besitzt vielfältige Schnittstellen, um den Winkelwert zu übertragen&lt;br /&gt;
&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |Seriell SSI&lt;br /&gt;
 |Standard Schnittstelle für Winkelencoder in der Industrie&lt;br /&gt;
 |-&lt;br /&gt;
 |PWM&lt;br /&gt;
 |erzeugt abhängig vom Winkel eine entsprechende Pulslänge, läßt sich sehr schön mit der Capturefunktion eines Controllers messen und braucht nur eine Leitung&lt;br /&gt;
 |-&lt;br /&gt;
 |I2C&lt;br /&gt;
 |direkte Schnittstelle zum Microcontroller&lt;br /&gt;
 |-&lt;br /&gt;
 |Analog&lt;br /&gt;
 |kompatible Schnittstelle um beispielsweise Potiapplikationen zu ersetzen&lt;br /&gt;
 |-&lt;br /&gt;
&lt;br /&gt;
 |Inkremental&lt;br /&gt;
 |klassische Schnittstelle um relative Bewegungen zu messen, keine Absolutmessung möglich&lt;br /&gt;
 |-&lt;br /&gt;
 |BLDC&lt;br /&gt;
 |erzeugt direkt die Kommutierung für einen bürstenlosen Motor. Durch die höhere Auflösung gegenüber einer 3-Hall-Schalterlösung kann der BLDC mit einem wesentlich höheren Drehmoment gestartet werden&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
[[Bild:AMS-magnet_354x421.jpg|left]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Bei der Auswahl des Magnets ist darauf zu achten, dass sogenannte Selten-Erde-Magnete verwendet werden. http://de.wikipedia.org/wiki/Seltene_Erden Diese erzeugen ein besonders starkes Magnetfeld, das im 1-Tesla-Bereich liegt. Im Zentrum des Magnetfelds ist ein linearer Bereich, der für die Genauigkeit der Messung ausschlaggebend ist. Solange die Hallsensoren in diesem Bereich liegen, kann eine unkalibrierte Genauigkeit von +/- 0.5 Grad gewährleistet werden. Weiterhin ist zu beachten, dass der Magnet nicht direkt auf eine Eisenwelle montiert wird. Die Eisenwelle verursacht quasi einen magnetischen 'Kurzschluss' und entzieht damit den Hallsensoren das Magnetfeld. Idealerweise sollte eine NE-Welle verwendet werden, oder wenn nicht anders machbar muss eine Isolation aus NE-Material zwischen Eisenwelle und Magnet eingefügt werden.&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Ein einfacher erfolgreicher Test des Sensors ist hier beschrieben: http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=322373#322373&lt;br /&gt;
&lt;br /&gt;
===Drehgeber Sharp GP1A30 und GP1A38===&lt;br /&gt;
&lt;br /&gt;
[[Bild:gp1a30.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Beim Sharp GP1A30 und GP1A38 handelt es sich um Gabellichtschranken mit inkrementaler Drehgeberfunktion. Beide sind im Grunde von den Anschlüssen identisch, lediglich kann GP1A38 noch etwas höhere Drehzahlen messen. Im Gegensatz zu herkömmlichen Gabellichtschranken können mit dieser sowohl Drehzahl als auch Drehrichtung ermittelt werden. Notwendig sind dafür nur 2 digitale Ports. Verzichtet man auf die Auswertung der Drehrichtung, reicht nur ein Port.&lt;br /&gt;
Der Sensor hat den Vorteil, dass die Signale bereits TTL-kompatibel sind und direkt an ein Controllerboard angeschlossen werden können. Ein Beispielprogramm zu [[RN-Control]] findet man hier&lt;br /&gt;
&lt;br /&gt;
* [[Beispiel Drehzahlmessung mit RN-Control]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:GP1A30.gif|center]]&lt;br /&gt;
&lt;br /&gt;
Die Auswertung inkrementaler Drehgeber ist recht einfach. Ein Ausgang liefert einen Impuls pro Markierung (Scheibe auf der Welle). Prüft man bei jedem Impuls (Flanke) noch gleichzeitig den aktuellen Pegel des zweiten Ausganges, so kann daraus die Drehrichtung abgeleitet werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Signalverlauf an den Sensorausgängen ist phasenversetzt:&lt;br /&gt;
&lt;br /&gt;
[[Bild:inkremental1.gif|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:drehgeber_an_rncontrol.gif|center|framed|Beispielschaltung, wenn man lediglich die Drehzahl ohne Drehrichtung auswerten möchte. Als Widerstand hat sich 330 Ohm als gut erwiesen.]]&lt;br /&gt;
&lt;br /&gt;
==Optische Sensoren==&lt;br /&gt;
===Helligkeit=== &lt;br /&gt;
Die Hauptanwendung solcher Sensoren ist, den hellsten Fleck im Raum zu finden.&lt;br /&gt;
Dies ist auch Teil vieler Roboterwettbewerbe. (Robo Callenge (2002 sic!), 'Ein Platz an der Sonne')&lt;br /&gt;
&lt;br /&gt;
Solche Sensoren können einfache [[LDR]]s oder [[Fotodiode|Photodioden]] bzw. [[Fototransistor|Phototransistoren]] sein.&lt;br /&gt;
LDRs haben den Vorteil, dass sie relativ hoch aussteuern, der große Nachteil ist aber, dass diese Sensoren ziemlich wärmeempfindlich und etwas träge sind.&lt;br /&gt;
Photodioden und Phototransistoren haben den Vorteil, dass sie sehr genau sind, aber nicht besonders hoch aussteuern. Diese sollte man evtl. über einen OpAmp verstärken.&lt;br /&gt;
&lt;br /&gt;
[[Bild:fotowiderstand.jpg|center|framed|Ein typischer Fotowiderstand]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:SFH300.jpg|center|framed|SFH300, ein typischer Phototransistor]]&lt;br /&gt;
&lt;br /&gt;
Alternativ kann auch ein digitaler Lichtsensor verwendet werden, den man direkt an den I2C- oder SM-Bus anschliessen kann. Man erspart sich Auswertung, Temperaturkompensation und Signalaufbereitung, allerdings ist der Anschluss meistens schwieriger, weil der Sensor in SMD-Bauform gebaut ist und 3,3 anstatt 5 Volt braucht.&lt;br /&gt;
[[Bild:Lichtsensor.jpg|center|framed|Ein digitaler Lichtsensor für den I2C-Bus (TSL2561 der Frima Taos)]]&lt;br /&gt;
&lt;br /&gt;
Die Suche nach dem hellsten Fleck im Raum ist wie ich finde ein gutes Einsteigerthema!&lt;br /&gt;
&lt;br /&gt;
===CNY70===&lt;br /&gt;
&lt;br /&gt;
Der CNY70 ist ein Foto-Reflex Optokoppler. In einem würfelförmigem Gehäuse befindet sich eine Infrarot LED als Sender und ein Infrarot Fototransistor als Empfänger. Damit kann auf kurze Entfernung (wenige Millimeter) das reflektierte Licht der IR-LED durch den IR-Fototransistor gemessen werden.  &lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[Bild:cny70.jpg|thumb|200px|CNY70]]&lt;br /&gt;
|[[Bild:cny70_pinout.jpg|framed|CNY70 Vishay Pinout]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Achtung:''' Es existiert auch noch ein CNY70 von Temic mit anderer Pinbelegung, dort ist der Fototransistor verdreht eingebaut.&lt;br /&gt;
&lt;br /&gt;
Der CNY70 eignet sich für eine Vielzahl von Sensoren. Z.B. als Liniensensor, Radencoder, Abgrunddetektor und Lichtschranke. Allerdings ist er empfindlich gegen Streulicht, da  das Licht der IR-LED nicht moduliert ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:cny70_schem1.gif|thumb|center|600px|CNY70 als Liniensensor]]&lt;br /&gt;
&lt;br /&gt;
Der Liniensensor benötigt 2 A/D Wandler Eingänge des Prozessors. Die CNY70 sollten so nah wie möglich in Bodennähe angebracht sein (1..3mm). Der P-Kanal FET BS250 dient als Schalter für die IR-LEDs des CNY70. Damit spart man Strom, wenn der Liniensensor nicht benötigt wird. Allerdings wird dafür ein weiterer Prozessor Ausgang als Enable Signal benötigt. HIGH Pegel schaltet die Sensor LEDs aus, LOW Pegel ein.  Wird keine Enable Funktion gewünscht, läßt man den BS250 einfach weg und hängt die Vorwiderstände der Sensor LEDs direkt an VCC.&lt;br /&gt;
&lt;br /&gt;
[[Bild:cny70_schem2.gif|thumb|center|600px|CNY70 als Radencoder mit Schmitt-Trigger]]&lt;br /&gt;
&lt;br /&gt;
Die Radencoder benötigen zwei digitale Eingangsports des Prozessors. A/D Wandler sind nicht nötig, da die Schmitt-Trigger Gatter für saubere Logik Signale sorgen. Die AVR Controller haben bereits Schmid-trigger Eingänge. Die CNY70 sollten so nah wie möglch an den Rädern sitzen (1..2mm). Die gewählten Widerstandswerte für R17/R19 bzw. R18/R20 sind optimiert für Radencoder die auf Transparentfolie gedruckt und auf Aluminium Räder aufgeklebt werden. Für Radencoder die auf Papier ausgedruckt werden, sind andere Widerstandswerte notwendig.&lt;br /&gt;
Der P-Kanal FET BS250 dient als Schalter für die IR LEDs des CNY70. Damit spart man Strom, wenn der Radencoder nicht benötigt wird. Allerdings wird dafür ein weiterer Prozessor Ausgang als Enable Signal benötigt. HIGH Pegel schaltet die Sensor LEDs aus, LOW Pegel ein. Wird keine Enable Funktion gewünscht, läßt man den BS250 einfach weg und hängt die Vorwiderstände der Sensor LEDs direkt an VCC. Ab ca. 3 V Versorgungsspannung können die 2 IR LEDs auch in Reihe geschaltet werden, um Strom zu sparen.&lt;br /&gt;
&lt;br /&gt;
===Distanzsensor IS471F===&lt;br /&gt;
&lt;br /&gt;
IS471F - Hinderniserkennung mit Infrarot Distanzsensor&lt;br /&gt;
&lt;br /&gt;
Das hier vorgestellte IC IS471F erlaubt eine einfache und sogar recht preisgünstige Hinderniserkennung per Infrarot. Dazu muss im Wesentlichen nur noch eine Infrarot-Diode an das IC angeschlossen werden. Das modulierte Licht wird von einem Gegenstand direkt auf das IC zurückgeworfen und somit das Hindernis erkannt. Tageslicht/Fremdlicht stört den IS471 überhaupt nicht, da das Licht mit einer bestimmten Frequenz moduliert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:is471.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der normale Schaltungsaufbau sieht also wie oben abgebildet aus! In der Praxis kann das dann in etwa so aussehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:is471beispiel.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das englische Datenblatt findet man im Roboternetz-Download-Bereich&lt;br /&gt;
&lt;br /&gt;
Die normale Reichweite ist in gewissen Grenzen abhängig von der Farbe des Hindernisses. In der Regel reicht sie jedoch einige cm, so dass langsame Roboter durchaus sehr gut damit zurechtkommen. Durch besonders helle Infrarot-LEDs und durch zusätzliche LED-Fassungen kann man die Reichweite erhöhen. Wem das noch nicht reicht, der kann über einen zusätzlichen Transistor die Strahlungsleistung der LED noch weiter erhöhen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:is471verstaerkung.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
http://www.roboternetz.de/bilder/mehrereis471.gif&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sharp Infrarotsensoren===&lt;br /&gt;
&lt;br /&gt;
Sharp hat eine ganz interessante Serie von Bausteinen herausgebracht, mit denen ein Roboter sogar recht genau Entfernungen messen kann. Das Messergebnis ist nahezu unabhängig von der Farbe und Helligkeit des gemessenen Objektes. Die Ansteuerung ist sehr einfach, der Sensorausgang kann zum Beispiel direkt an einen analogen Eingang eines Mikrocontrollers angeschlossen werden. Die Sensoren sind unter den Roboter-Bastlern weit verbreitet. &lt;br /&gt;
Bei vielen Händlern erhältlich kosten die Sensoren derzeit je nach Typ und Händlerspanne zwischen 13 bis 25 Euro.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sharpentfernungssensor.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Oft werden selbst in kleinen Roboter-Projekten mehrere dieser Sensoren genutzt, da sie nur einen äußerst engen Erfassungsbereich haben. Sie eignen sich daher sehr gut zur Vermessung einer Umgebung, insbesondere dann, wenn sie drehbar auf einem Servo montiert werden. Als Kollisionsschutz sind sie wegen des engen Winkels nur bedingt geeignet, zu diesem Zweck eignen sich zum Beispiel Ultraschallsensoren besser.&lt;br /&gt;
Das Funktionsprinzip der Sensoren ist einfach. Der Sensor besteht aus Sender und Empfänger. Der Sender sendet einen Infrarot-Strahl aus, der vom Hindernis reflektiert wird. Je nach Entfernung trifft der reflektierte Strahl an einer unterschiedlichen Stelle auf den Empfänger (ein sog. Position Sensitive Device, PSD). Der Empfänger setzt den Auftreffpunkt in einen analogen Spannungswert um. Eine schöne Skizze dazu:  &lt;br /&gt;
&lt;br /&gt;
[[Bild:sharpfunktion.jpg|center]]&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Wenn man diese Sensoren an Robotern einsetzt, will man meist Hindernisse mit senkrecht stehenden Kanten erkennen. Montiert man den Sensor jedoch in waagrechter Lage, können sich Fehlmessungen ergeben, wenn sich ein Objekt am Sensor vorbeibewegt (z.B. wenn sich der Roboter dreht). Es wird an der Kante kurzzeitig eine Entfernung gemessen, die geringer als die tatsächliche Entfernung zum Hindernis ist (oder auch größer als die Entfernung zu einem zweiten Hindernis hinter dem ersten, je nach Bewegungsrichtung!). Man löst dieses Problem, indem man den Sensor in senkrechter Position montiert, also so, dass die beiden Linsen übereinander statt nebeneinander liegen. Dies wird auch im Datenblatt des Sensors empfohlen: der Sensor sollte immer senkrecht zur Bewegungsrichtung des Hindernisses montiert werden.&lt;br /&gt;
&lt;br /&gt;
Sehr deutlich erkennt man diese Messfehler, wenn man den Sensor als eine Art 3D-Scanner einsetzt: http://www.team-iwan.de/technik/sharp1.php&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{|{{Blaueschmaltabelle}}&lt;br /&gt;
|&lt;br /&gt;
Die Gehäuse dieser Sensoren sehen wie ganz gewöhnlicher Kunststoff aus. Sie bestehen jedoch aus leitfähigem Material! (Kaum zu glauben, aber einfach nachprüfbar: zwischen den beiden Befestigungslöchern misst man einen Widerstand von etwa 250 bis 300 Ohm). Außerdem ist das Gehäuse mit dem Masseanschluss verbunden. Dies ist normalerweise nicht weiter wichtig, da die Sensoren meist entweder isoliert (zB auf Kunststoffteilen) oder auf einem geerdeten/mit Masse verbundenen Metallchassis montiert werden. Wenn man aber die Sensoren abschalten will, um Strom zu sparen (die Sensoren verbrauchen etwa 30 bis 40mA), muss man bei nicht isolierter Montage unbedingt die Plusleitung schalten! Wenn man die Masse-Zuleitung unterbricht, ist der Sensor sonst trotzdem noch über das Gehäuse und das Chassis mit Masse verbunden und wird nicht deaktiviert!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Einige der beliebtesten Bausteine sind:'''&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D12==== &lt;br /&gt;
Distanz 10-80 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt.&lt;br /&gt;
Dies ist der am häufigsten eingesetzte Sharp-Typ bei mobilen Robotern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:GP2D12anschluss.gif|center]]&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2YA21YK==== &lt;br /&gt;
Distanz 10-80 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt.&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D120====&lt;br /&gt;
Distanz 4-30 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt.&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2Y0A02YK====&lt;br /&gt;
Distanz 20-150 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
http://www.shop.robotikhardware.de/shop/catalog/images/artikelbilder/sensoren/gp2y0a02yk_diagramm.gif&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D02====&lt;br /&gt;
Distanz 10-80 cm - Entfernung wird durch 8-Bit-Digitalausgang übermittelt.&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D150====&lt;br /&gt;
Distanz 3-30 cm - 1 Bit Schaltausgang.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Datenblätter zu den oberen Sensoren findet man im Download-Bereich des Roboternetzes, siehe unter [[#Weblinks]].&lt;br /&gt;
 &lt;br /&gt;
Um die analogen Spannungen der Sensoren in eine Entfernung umzurechnen, kann man sich mit Hilfe des Datenblattes oder einfacher Probemessungen Tabellen erstellen, welche dann vom Controller zur Umsetzung genutzt werden.&lt;br /&gt;
Bequemer ist allerdings eine Näherungsformel:&lt;br /&gt;
&lt;br /&gt;
====Formel zur Entfernungsberechnung==== &lt;br /&gt;
 D = A/(X-B) &lt;br /&gt;
&lt;br /&gt;
 D ist die Entfernung &lt;br /&gt;
 X ist der Ausgabewert des Sensors &lt;br /&gt;
 A ist die Steigung der Kurve A/X &lt;br /&gt;
 B ist der Offset der Kurve &lt;br /&gt;
&lt;br /&gt;
Die Konstanten A und B ermittelt man am besten über zwei Probemessungen: &lt;br /&gt;
&lt;br /&gt;
D und X sind die Entfernung und der Ausgabewert der ersten Messung (z.B. bei 20 cm) &lt;br /&gt;
D' und X' sind die Entfernung und der Ausgabewert der zweiten Messung (z.B. bei 60 cm) &lt;br /&gt;
&lt;br /&gt;
 A = ((X' - X) * D' * D) /(D - D' ) &lt;br /&gt;
 B = (D' * X' - D * X) /(D' - D) &lt;br /&gt;
&lt;br /&gt;
====GP2D12 Messkurve====&lt;br /&gt;
&lt;br /&gt;
[[Bild:gpd12kurve.gif|center]]&lt;br /&gt;
&lt;br /&gt;
====GPD120 Messkurve====&lt;br /&gt;
&lt;br /&gt;
[[Bild:gpd120kurve.gif|center]]&lt;br /&gt;
&lt;br /&gt;
==Ultraschall Sensoren== &lt;br /&gt;
===Ultraschallsensoren SRF04===&lt;br /&gt;
Die Firma '''Devantech''' hat eine Serie von sehr günstigen und kleinen Ultraschallsensoren entwickelt, die sich im Bereich &amp;quot;autonome Robotersysteme&amp;quot; durchgesetzt haben. Sie sind sehr verbreitet, da sie auch für &amp;quot;Hobby-Robotiker&amp;quot; erschwinglich sind und es sich nicht lohnen würde vergleichbare Module selber zu bauen, da diese meistens ungenauer und teurer wären.&lt;br /&gt;
&lt;br /&gt;
Bekannt wurde die Serie durch den '''SRF04'''. Mit seinen kleinen Abmessungen, der niedrigen Stromaufnahme und der hohen Genauigkeit ist er für kleine Messaufgaben im Entfernungsbereich von 3 cm bis 3 m gut geeignet. Der SRF04 kann einen 3 cm dicken Besenstiel in 2 m Entfernung erkennen und wird durch ein [[PWM]]-Signal ausgewertet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf_04a.jpg]] [[Bild:srf_04.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Ultraschallsensor SRF05===&lt;br /&gt;
Der Nachfolger des SRF04 ist der neue SRF05. Er besitzt noch eine etwas höhere Reichweite bis 4 Meter. Zudem besitzt er neben dem kompatibel Mode zu SRF04 noch eine Betriebsart bei der er über einen einzigen Port (Pin) gesteuert wird. Das heißt sowohl der Start der Messung und das Ergebnis wird über die gleiche Leitung übertragen. [[Ultraschall SRF05 an RN-MiniControl|Programmbeispiel in Bascom]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Srf05mode1.jpg|center]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf05mode2.gif|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf05mode2diagram.gif|center]]&lt;br /&gt;
&lt;br /&gt;
===SRF08===&lt;br /&gt;
Die Alternative zu SRF04 und SRF05 ist der beliebte  '''SRF08''' und dessen Nachfolger '''SRF10''', der nun über den [[I2C]]-Bus ausgewertet werden kann und über eine Reichweite von 3 cm bis 6 m verfügt. Er hat eine noch kleinere Stromaufnahme und zusätzlich befindet sich auf der Platinenfront ein Fotowiderstand (LDR), dessen Lichtmesswerte sich ebenfalls über den [[I2C]]-Bus auswerten lassen. Durch den SRF08 wird es möglich, auch bis zu 16 Mehrfachechos von weiter hinten gelegenen Gegenständen auszuwerten, die bei dem SRF04 ignoriert wurden. Über den [[I2C]]-Bus kann man die Messwerte in Zentimeter, Zoll und in der Laufzeit µs auslesen und spart sich somit die externe Auswertung der Laufzeit wie bei dem SRF04. Weiterhin können insgesamt 16 SRF08-Module an einen [[I2C]]-Bus angeschlossen werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf08_a.jpg]]  [[Bild:srf08_b.jpg]]&lt;br /&gt;
&lt;br /&gt;
===SRF08 Programmbeispiel===&lt;br /&gt;
&lt;br /&gt;
[[SRF08 mit avr-gcc|SRF08 Programmbeispiel mit AVR-GCC]]&lt;br /&gt;
&lt;br /&gt;
SFR08 Programmbeispiel mit [[Bascom]]&lt;br /&gt;
Über die grundsätzliche Behandlung des [[I2C]]-Bus mit [[Bascom]] kann man [[I2C|hier]] nachlesen. &lt;br /&gt;
&lt;br /&gt;
 Const Sf08_adr_0 = &amp;amp;HE0             ' I2C Adresse&lt;br /&gt;
 Const Sf08_c_range = 100            ' Reichweite&lt;br /&gt;
 Const Sf08_c_gain = 1               ' Empfindlichkeit&lt;br /&gt;
&lt;br /&gt;
Die Adresse ist der Default-Wert für den Sensor und kann eingestellt werden. &lt;br /&gt;
Range und Gain sind anzupassen, die angegebenen Werte sind aber mal grundsätzlich verwendbar.&lt;br /&gt;
&lt;br /&gt;
'''Setup'''&lt;br /&gt;
Nach dem Reset sind einmal Range und Gain zu setzen.&lt;br /&gt;
&lt;br /&gt;
'''Setzen Range'''&lt;br /&gt;
&lt;br /&gt;
      I2cstart&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 2            ' register &amp;quot;range&amp;quot;&lt;br /&gt;
      I2cwbyte Sf08_c_range  &lt;br /&gt;
      I2cstop&lt;br /&gt;
 &lt;br /&gt;
'''Setzen Gain'''&lt;br /&gt;
&lt;br /&gt;
      I2cstart&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 1            ' register &amp;quot;gain&amp;quot;&lt;br /&gt;
      I2cwbyte Sf08_c_gain    &lt;br /&gt;
      I2cstop&lt;br /&gt;
&lt;br /&gt;
'''Abfrage Trigger'''&lt;br /&gt;
&lt;br /&gt;
Die Abfrage soll laut Beschreibung in zwei Schritten erfolgen, zwischen denen ca 70 mS gewartet werden soll. Diese Zeit braucht das Gerät zum Messen. &lt;br /&gt;
&lt;br /&gt;
'''Trigger'''  &lt;br /&gt;
      I2cstart&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 0            ' register &amp;quot;Trigger&amp;quot;&lt;br /&gt;
      I2cwbyte 81           ' Meßwert in Zentimetern&lt;br /&gt;
&lt;br /&gt;
      Waitms 70 &lt;br /&gt;
&lt;br /&gt;
'''Ergebnis abholen'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 DIM Lsb as Byte&lt;br /&gt;
 DIM Msb as Byte&lt;br /&gt;
 DIM IVal as word&lt;br /&gt;
&lt;br /&gt;
      I2cstart              ' Repeated Start&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 2            ' Meßwert US&lt;br /&gt;
&lt;br /&gt;
      I2cstart                 ' repeated Start&lt;br /&gt;
      I2cwbyte Sf08_adr_0 + 1  ' Device I2C Adresse READ!&lt;br /&gt;
      I2crbyte Msb , Ack      ' Bit 8-15&lt;br /&gt;
      I2crbyte Lsb , Nack     ' Bit 0-7&lt;br /&gt;
      I2cstop&lt;br /&gt;
&lt;br /&gt;
      Ival = Makeint(lsb , Msb) ' umwandeln in Word (16 Bit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SRF10 Ultraschallsensor ===&lt;br /&gt;
SRF10 ist quasi der Nachfolger von SRF08. Er bietet die gleiche Leistung und ist sogar gegenüber Spannungsschwankungen noch etwas unempfindlicher als der Vorgänger. Der größte Vorteil besteht jedoch darin das er ca. 1/3 kleiner als sein Vorgänger ist. Allerdings bietet er im Gegensatz zum SRF08 weder einen Lichtsensor noch die Möglichkeit, die Mehrfachechos auszulesen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf10foto1.jpg]] [[Bild:srf10foto2.gif]]&lt;br /&gt;
&lt;br /&gt;
Die technischen Daten sind ähnlich:&lt;br /&gt;
* Betriebsspannung: 5V &lt;br /&gt;
* Stromaufnahme: ca. 3mA Standby, ca. 15mA während des Messens Frequenz: 40KHz &lt;br /&gt;
* Maximale Reichweite: 6 m &lt;br /&gt;
* Minimale Reichweite: 4 cm &lt;br /&gt;
* Messwerterfassung: intern, kein externer Controller zur Zeitmessung notwendig &lt;br /&gt;
* Interface: Standard – I2C (passend zu zahlreichen Controllerboards, z.B. RN-Control) &lt;br /&gt;
* Ausgabeformat: µs, cm oder Zoll &lt;br /&gt;
* Feature: Analogverstärkung 40 - 700 (einstellbar, 16 Stufen) &lt;br /&gt;
* Abmessungen: 32mm x 15mm x 10mm &lt;br /&gt;
* Hersteller: Devantech Ltd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[Ultraschall_SRF10_an_RN-Control|Programmbeispiel in Bascom]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf10ausbreitung.gif|center]]&lt;br /&gt;
&lt;br /&gt;
===SRF02 Ultraschallsensor===&lt;br /&gt;
Der erste Sensor aus der SRF-Reihe, der mit nur einem Ultraschallwandler auskommt. Dennoch können sich die Leistungen zeigen. Vor allem die Tatsache, dass sowohl RS232- und I2C-Bus-Schnittstelle vorhanden ist, dürfte viele Bastler erfreuen.&lt;br /&gt;
&lt;br /&gt;
* Betriebsspannung 5V (stabilisiert) &lt;br /&gt;
* Stromaufnahme nur 4mA (typisch) &lt;br /&gt;
* Ultraschallfrequenz 40kHz &lt;br /&gt;
* Reichweite 15 cm bis 6 Meter &lt;br /&gt;
* Schnittstelle RS232 (TTL) und I2C-Bus &lt;br /&gt;
* Ausgabeeinheit wahlweise mm, inch oder uS &lt;br /&gt;
* Einfachste Verwendung, keine Kalibration/Justierung notwendig&lt;br /&gt;
* Größe 24mm x 20mm x 17mm &lt;br /&gt;
&lt;br /&gt;
[[Bild:srf02_germany.jpg]]&lt;br /&gt;
&lt;br /&gt;
Einige Bascom-Programmbeispiele zum SRF02 findet man unter [[Ultraschallsensor SRF02 am RN-Board]]&lt;br /&gt;
&lt;br /&gt;
=== Vergleichstabelle ===&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Blaueschmaltabelle}}&lt;br /&gt;
 |&lt;br /&gt;
 |'''SRF10'''&lt;br /&gt;
 |'''SRF08'''&lt;br /&gt;
 |'''SRF05'''&lt;br /&gt;
 |'''SRF04'''&lt;br /&gt;
 |'''SRF02'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Betr. Spannung'''&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Stromaufnahme'''&lt;br /&gt;
 |3mA typ.,&amp;lt;br&amp;gt; 15mA max.&lt;br /&gt;
 |3mA typ.,&amp;lt;br&amp;gt; 15mA max.&lt;br /&gt;
 |4mA typ.,&amp;lt;br&amp;gt; 30mA max.&lt;br /&gt;
 |30mA typ.,&amp;lt;br&amp;gt; 50mA max.&lt;br /&gt;
 |4mA typ.&amp;lt;br&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
 |-&lt;br /&gt;
 |'''US Leistung'''&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |?? mW&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Frequenz'''&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Bereich'''&lt;br /&gt;
 |72&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Reichweite'''&lt;br /&gt;
 |4cm - 6m&lt;br /&gt;
 |3cm - 6m&lt;br /&gt;
 |3cm - 4m&lt;br /&gt;
 |3cm - 3m&lt;br /&gt;
 |15cm - 6m&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Triggerimpuls'''&lt;br /&gt;
 |&lt;br /&gt;
 |&lt;br /&gt;
 |10µs min.&lt;br /&gt;
 |10µs min.&lt;br /&gt;
 |&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Abmessung in mm'''&lt;br /&gt;
 |32 x 15 x 10&lt;br /&gt;
 |43 x 20 x 17&lt;br /&gt;
 |43 x 20 x 17&lt;br /&gt;
 |43 x 20 x 17&lt;br /&gt;
 |24 x 20 x 17&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Interface'''&lt;br /&gt;
 |I2C&lt;br /&gt;
 |I2C&lt;br /&gt;
 |TTL Impuls&lt;br /&gt;
 |TTL Impuls&lt;br /&gt;
 |I2C o. RS232 TTL&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Feature'''&lt;br /&gt;
 |Minimodul&lt;br /&gt;
 |Lichtsensor&lt;br /&gt;
 |SRF04 Modus&lt;br /&gt;
 |&lt;br /&gt;
 |nur 1 US-Kapsel&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Preis ca. *'''&lt;br /&gt;
 |44,00 €&lt;br /&gt;
 |44,00 €&lt;br /&gt;
 |22,00 €&lt;br /&gt;
 |25,00 €&lt;br /&gt;
 |19,00 €&lt;br /&gt;
 |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''*''' Der Preis dient nur zum Vergleich untereinander, nicht als Referenz !&lt;br /&gt;
&lt;br /&gt;
==Kompaß== &lt;br /&gt;
===Kompass-Modul CMPS03===&lt;br /&gt;
Laut der Doku ist diese Modul speziell für die Bedürfnisse von Robotern gestaltet worden. Es misst seine Lage relativ zum Erdmagnetfeld und liefert diesen Wert&lt;br /&gt;
* Als PWM-Signal &lt;br /&gt;
* Über I2C entweder 0-255 als Byte oder&lt;br /&gt;
* 0-3599 als 16-Bit Wert (MSB first)&lt;br /&gt;
&lt;br /&gt;
In der vorliegenden Doku ist eine fixe I2C-Adresse von 0xC0 angegeben. Was leider noch fehlt, sind Angaben, ob und wie diese Adresse geändert werden kann.&lt;br /&gt;
&lt;br /&gt;
Bei waagrechter(!) Montage ist das also ein Kompass, bei senkrechter Montage dieser Module kann man auch die Neigung in Nord-Süd-Richtung messen. Hierzu sind 2 Module nötig, die zueinander um 90° gedreht angeordnet sein müssen. Die Neigung in Ost-West-Richtung zu messen, ist dagegen leider nicht möglich. Wenn ein CMPS03 als Kompass verwendet werden soll, sind zwei Dinge zu beachten: &lt;br /&gt;
* Mindestens 20 cm Abstand von Eisen (Motoren)&lt;br /&gt;
* Exakte horizontale Ausrichtung.&lt;br /&gt;
Eine Montage an einem langen Stab aus Holz oder Kunststoff hoch über dem Roboter ist sinnvoll. &lt;br /&gt;
&lt;br /&gt;
Das Ganze ist eine Anwendung des Philips-KMZ51 Magnet-Feld-Sensors mittels eines PIC16F872&lt;br /&gt;
&lt;br /&gt;
Gelegentlich sollte das Modul kalibriert werden. Das kann über den I2C-Bus, aber auch mittels einen Pins am Modul initiiert werden. Dafür muss am Pin 6 für jede Himmelsrichtung einmal kurz GND angelegt werden. Diese 4 Messpunkte nimmt das Modul auf und speichert sie im EEPROM. &lt;br /&gt;
&lt;br /&gt;
Ein Beispielprogramm findet man hier:&lt;br /&gt;
* [[Bascom und Kompass CMPS03]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:cmps3pin.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Beschleunigung==&lt;br /&gt;
&lt;br /&gt;
Beschleunigungssensoren messen die Beschleunigung, die auf sie wirkt - wenn sie auf dem Tisch liegen, messen sie beispielsweise die Erdbeschleunigung von 1g. In einem Auto können weitere Beschleunigungen hinzukommen: Zur Seite beim Kurvenfahren, nach vorne oder hinten beim Beschleunigen, oder bei zügiger Fahrt über eine Bergkuppe auch mal welche in vertikaler Richtung.&amp;lt;br&amp;gt;&lt;br /&gt;
Beschleunigungssensoren sind meist mehrdimensional ausgelegt, so dass für mehrere Achsen ein Sensor verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
[[Bild:beschleunigungssensor_rh.gif|center]]&lt;br /&gt;
&lt;br /&gt;
Anwendungen finden sie in ESP-Systemen in Autos, die u.a. über die Querbeschleunigung ausrechnen können, ob das Fahrzeug seitlich driftet oder gar schleudert.&amp;lt;br&amp;gt;&lt;br /&gt;
Eine andere wichtige Aufgabe übernehmen sie zusammen mit Gyroskopen in Trägheitsnavigationssystemen, die dann sowohl die Lage im Raum als auch die Bewegung feststellen können.&lt;br /&gt;
&lt;br /&gt;
Moderne Piezo-Sensoren sind nur noch chip-gross und können direkt in Schaltungen integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele für solche Chips ist die Chipfamilie [[ADXL]] von Analog Devices. Sie umfaßt 1- und 2-Achs Accelerometer in verschiedenen Empfindlichkeiten. Der Test eines solchen Sensors ist hier beschrieben. http://www.roboternetz.de/phpBB2/viewtopic.php?t=8525&lt;br /&gt;
&lt;br /&gt;
==Drehung==&lt;br /&gt;
&lt;br /&gt;
Um Drehungen zu messen, werden sogenannte Gyroskope, kurz &amp;quot;Gyros&amp;quot; verwendet. Typische Vertreter sind hier die [[ADXRS]]-Familie von Analog Devices. Diese sind allerdings, anders als die Beschleunigungssensoren, meistens nur für eine Achse ausgelegt. Die Ausgabe erfolgt meist analog, jede Ausgangsspannung entspricht einer bestimmten Drehrate in °/Sekunde.&lt;br /&gt;
&lt;br /&gt;
Gemessen wird die Auswirkung der Corioliskraft auf zwei gleiche, in Bewegung gehaltene Massen. Diese schwingen radial, d.h. 90° verdreht zu der Achse, auf der die Drehung gemessen werden soll. Wird der Sensor um die Achse gedreht, ändert sich die Geschwindigkeit dieser Massen, da sie auf einer gedachten Scheibe abwechselnd nach innen und außen wandern. Je weiter sie außen sind, desto höher ist ihre Geschwindigkeit, je weiter innen, desto langsamer sind sie. Bei der Bewegung nach außen müssen sie also beschleunigt werden, andersherum genauso. Die dabei auftretenden Beschleunigungen werden mittels einiger Fühler gemessen, die einen Plattenkondensator bilden.&lt;br /&gt;
&lt;br /&gt;
Eine Anwendung sind im Flugmodellbau Gyro-&amp;quot;Taillocks&amp;quot;, die in Hubschraubern die Heckstabilität verbessern und ESP-Systeme in Autos, die u.a. durch die Messung der Gierrate, also der Drehung des Fahrzeugs um die Hochachse, feststellen können, ob das Fahrzeug seitlich driftet oder sogar schleudert.&lt;br /&gt;
&lt;br /&gt;
==Geschwindigkeit==&lt;br /&gt;
&lt;br /&gt;
Geschwindigkeit kann unterschiedlich erfasst werden.&lt;br /&gt;
* Direkt am Rad oder Antrieb. Diese Methode wird häufig auch in Kfz verwendet, stößt jedoch an ihre Grenzen, wenn die Räder viel Schlupf haben. &lt;br /&gt;
* Gegenüber der Luft mittels [[Pitot-Tube]]. Das wird bei Flugzeugen so gemacht, oder z.B. in der Formel 1. Bei niedrigen Geschwindigkeiten nicht zu gebrauchen&lt;br /&gt;
* Mittels eines optischen Sensors gegenüber dem Untergrund. Dafür kann ein [[Maussensor]] aus einer optischen Maus verwendent werden, evtl. mit einer Anpassung der Optik für einen geänderten Abstand.&lt;br /&gt;
* Mittels GPS-Empfang. Funktioniert nur unter freiem Himmel.&lt;br /&gt;
Siehe auch unter [[Sensoren für die Geschwindigkeitsmessung]]&lt;br /&gt;
&lt;br /&gt;
==Temperatur== &lt;br /&gt;
===NTCs===&lt;br /&gt;
NTCs (Negative Temperature Coefficient) oder Heißleiter sind stromleitende Materialien, die bei hohen Temperaturen Strom besser leiten als bei tiefen, das heißt, mit steigender Temperatur sinkt ihr elektrischer Widerstand. Siehe auch unter [[NTC]]. Ein großer Vorteil ist die leichte Anwendung und der geringe Preis. Nachteil ist, dass der Widerstandswert sich nicht linear mit der Temperatur verändert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:ntc.gif]]&lt;br /&gt;
&lt;br /&gt;
===PTCs===&lt;br /&gt;
&lt;br /&gt;
PTCs sind Temperatursensoren, deren Widerstand sich mit steigender Temperatur erhöht. Dazu gehören&lt;br /&gt;
&lt;br /&gt;
*PT100, PT1000 etc.&lt;br /&gt;
*Die KTYxx-xxx Reihe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== KTY: Silizium Temperatursensoren ====&lt;br /&gt;
&lt;br /&gt;
Die KTY-Temperatursensoren sind verglichen mit anderen Temperatursensoren verhältnismäßig günstig, haben dafür aber auch mehr Nachteile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Genauigkeit ist ziemlich eingeschränkt, weshalb die KTY-Temperatursensoren zuerst kalibriert werden sollten. Dies muss schaltungstechnisch oder in Software erfolgen, eine eingebaute Kalibrierung gibt es nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
Andererseits lassen sich mittels Oversampling sehr hoch aufgelöst Temperaturen messen, was aufgrund mittelmäßiger Linearität (auch nach der Linearisierung) aber nur bei der Messung kleiner Temperaturunterschiede empfehlenswert ist.&amp;lt;br&amp;gt;&lt;br /&gt;
Linearisiert werden die KTY an 5 Volt mit einem Reihenwiderstand von etwa 2,7 kOhm bis 3,3 kOhm.&amp;lt;br&amp;gt; &lt;br /&gt;
http://www.roboternetz.de/phpBB2/viewtopic.php?p=342164&amp;amp;sid=ad63fd51eb08bcf225389af5bbc4fcfd#342164&lt;br /&gt;
&lt;br /&gt;
==== Diode als Temperatursensor ====&lt;br /&gt;
Die Flußspannung von Dioden ist temperaturabhängig. Für Siliziumdioden verringert sich die Spannung um etwa 2 mV pro Grad Temperaturerhöhung. Der Absolutwert der Flußspannung hängt vom Strom ab und variiert auch zwischen verschiedenen Chargen. Es ist also fast immer wenigstens ein Abgleich nötig.&lt;br /&gt;
&lt;br /&gt;
===LM335 und LM35===&lt;br /&gt;
&lt;br /&gt;
[[Bild:LM335.JPG|center]]&lt;br /&gt;
&lt;br /&gt;
Der Temperatursensor LM335 funktioniert wie eine Z-Diode, die ihre Durchbruchspannung proportional zur Temperatur ändert. Beim Sensor LM335 beträgt diese Änderung 10mV/K, beim Sensor LM35 beträgt die Änderung 10mV/&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C. &lt;br /&gt;
&lt;br /&gt;
Der größte Unterschied zwischen den Sensoren ist der, dass am Ausgang des LM335 bei 0&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C etwa 2,73V anliegen (273K = 0&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C) und beim LM35 0V. Sollen negative Temperaturen gemessen werden, so muss man für den LM35 das Bezugspotential GND anheben (z.B. mit zwei Si-Dioden).&lt;br /&gt;
&lt;br /&gt;
Von den Sensoren LM335 und LM35 gibt es auch noch genauere Ausführungen, welche einen geringeren Temperatur-Fehler ab Werk haben. Diese Versionen heißen LM15/LM25 bzw. LM135/LM235 und sind entsprechend teurer als die 3er Version (zum Vergleich: LM335 kostet bei Reichelt 0,89€, der LM135 jedoch 7,75€). &lt;br /&gt;
&lt;br /&gt;
Der LM335 und LM35 messen nach einer einfachen Kalibrierung mit einem Poti, bis auf 1&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C genau. Dazu muss man mit dem Poti die Ausgangsspannung bei 25&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C auf 2,98V einstellen (2,98V / 0,01V/K = 298K = 25&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C). Da der Sensor über seinen Messbereich  sehr linear ist, braucht man nur bei einer Temperatur kalibrieren. Durch den Einsatz mehrerer in Reihe geschalteter Sensoren kann man das Ausgangssignal verstärken (bei drei LM335 erhält man dann 30mV/K anstatt 10mV/K) oder, wenn die Sensoren im Raum verteilt sind, einen einfachen Mittelwert bilden.&lt;br /&gt;
&lt;br /&gt;
====Beschaltung und Dimensionierung eines LM335====&lt;br /&gt;
[[Bild:lm335schaltung.jpg|center]]&lt;br /&gt;
Da sich der Sensor wie eine Z-Diode verhält, muss der Strom durch diese begrenzt werden, um eine Verfälschung des Signals oder gar eine Zerstörung zu verhindern. Fließt jedoch zu wenig Strom durch die Diode, so treten Störungen auf und die Genauigkeit sinkt.&lt;br /&gt;
&lt;br /&gt;
Der Strom wird auf einfache Weise wie bei einer LED durch einen Widerstand (hier R1) begrenzt. Der Strom sollte zwischen mindestens 450µA und maximal 5mA liegen. Bei einer Betriebsspannung von 5V kann also für 2mA ein Widerstand von etwa 2,5kOhm benutzt werden (R = U/I). &lt;br /&gt;
&lt;br /&gt;
Die max. Betriebsspannung sollte 30V nicht überschreiten!&lt;br /&gt;
&lt;br /&gt;
Zur Kalibrierung schließt man an ein 10kOhm Potentiometer zwischen V+ und V- (GND) des Sensors an und legt dessen Schleifer auf den ADJ-Pin. Nun stellt man die Ausgangsspannung in Abhängigkeit von der Raumtemperatur (welche bekannt sein sollte) ein (1&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C = 1K, 273K = 0&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C). Kalibriert man den LM335 nicht, so kann dieser um bis zu 9K falsch gehen!&lt;br /&gt;
&lt;br /&gt;
Im letzten Bild (ganz rechts) ist die schon angesprochene Reihenschaltung aufgezeichnet. Um ein größeres Ausgangssignal zu erhalten, kann man das Signal auch mit einem [[Operationsverstärker#Verstärker|Operationsverstärker]] verstärken. Das ist günstiger und man hat die Möglichkeit, das Signal um ein Vielfaches zu verstärken ohne einige Dutzend Sensoren einzusetzen!&lt;br /&gt;
&lt;br /&gt;
Pin-Belegungen und weitere Daten finden sich im Datenblatt (kann man z.B. bei Reichelt herunterladen).&lt;br /&gt;
&lt;br /&gt;
===Temperatur-Sensor LM75===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:lm75.gif|center]]&lt;br /&gt;
&lt;br /&gt;
Dieser Chip von National Semiconductors kann die Umgebungstemperatur mit einer Auflösung von 0.5&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt; Grad Celsius messen und wird über einen I2C Bus angesprochen. &lt;br /&gt;
&lt;br /&gt;
Der Messbereich: &lt;br /&gt;
*−25&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bis 100&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bei ±2&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C(max)Genauigkeit.&lt;br /&gt;
*−55&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bis 125&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bei ±3&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C(max)Genauigkeit. &lt;br /&gt;
&lt;br /&gt;
Der LM75 bietet:&lt;br /&gt;
* Einen Schaltausgang (invertierbar) - z.B. für Ventilator, Heizung etc.&lt;br /&gt;
* Programmierbarer oberer und unterer Schaltpunkt.&lt;br /&gt;
* Schaltausgang alternativ auch als Interrupt verwendbar.&lt;br /&gt;
* Über von außen einstellbare I2C-Adresse. Bit 0 = R/W, Bits 1-3 einstellbar, Bit 4-7 fixe Adresse 0x9n &lt;br /&gt;
* Maximal 8 Stück LM75 an einem I2C Bus. &lt;br /&gt;
&lt;br /&gt;
Durch I2C-Lesebefehle kann man die Temperatur (2x8Bit)auslesen.&lt;br /&gt;
&lt;br /&gt;
Das erste Byte ist der Temperatur-Vorkommawert in ganzen Grad, als normales signed char. Das Bit 7 vom zweiten Byte bestimmt den Nachkommawert. Wenn Bit 7 gleich 1 so ist der Nachkommawert + 0.5&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C. Auch dann + 0.5 &amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C wenn Vorkommawert negativ. Wenn Bit 7 gleich 0 so ist der Nachkommawert = 0. Bit 0-6 vom zweiten Byte sind ohne Bedeutung.&lt;br /&gt;
&lt;br /&gt;
===Programm-Beispiel für LM75===&lt;br /&gt;
Der LM75 wird über den [[I2C]]-Bus angesprochen.&lt;br /&gt;
In BasCom, wo es ja keine signed char gibt, wird das Interpretieren auf sehr unterschiedliche Art empfohlen. &lt;br /&gt;
&lt;br /&gt;
Ich empfehle:&lt;br /&gt;
&lt;br /&gt;
 dim Ival as integer&lt;br /&gt;
 dim Msb as byte&lt;br /&gt;
 dim Lsb as byte&lt;br /&gt;
         I2cstart&lt;br /&gt;
         I2cwbyte &amp;amp;H91   ' Lese-adresse !  &lt;br /&gt;
         If Err = 1 Then&lt;br /&gt;
            I2cstop       ' kein ACK vom LM75 --&amp;gt; irgendein Fehler&lt;br /&gt;
            Ival = 9999   ' Zeichen, daß der Wert ungültig ist !&lt;br /&gt;
         Else&lt;br /&gt;
            I2crbyte Msb , Ack&lt;br /&gt;
            I2crbyte Lsb , Nack&lt;br /&gt;
            I2cstop&lt;br /&gt;
            If Msb.7 = 1 Then&lt;br /&gt;
               Ival = Makeint(msb , &amp;amp;HFF)   ' auffüllen mit den Vorzeichen bits&lt;br /&gt;
            Else&lt;br /&gt;
               Ival = Makeint(msb , &amp;amp;H00)   ' positiv, also bleibt es so&lt;br /&gt;
            End If&lt;br /&gt;
            Ival = Ival * 10                ' erweitern &lt;br /&gt;
            If Lsb.7 = 1 Then&lt;br /&gt;
              Ival = Ival + 5               ' fünf Zehntel Grad dazu &lt;br /&gt;
            End If&lt;br /&gt;
         End if&lt;br /&gt;
&lt;br /&gt;
Man erhält als Ergebnis die Temperatur in 0,5 Grad Schritten (Natürlich nur, wenn's keine Fehler gab).&lt;br /&gt;
&lt;br /&gt;
Ein weiteres Beispiel [http://www.darc-coburg.de/modules/wiwimod/index.php?page=LM75]&lt;br /&gt;
&lt;br /&gt;
==Resistive Sensoren==&lt;br /&gt;
Resistive Sensoren bzw. Linearpotentiometer arbeiten als Spannungsteiler über einer Hybridleitplastik- schicht und sind in unterschiedlichen Bauformen erhältlich; z.B. für Zylindereinbau, Klemmbock- u. Gelenkaugenbefestigung oder Taster.&lt;br /&gt;
Deren Einsatzgebiete sind vorwiegend in der Industrie.&lt;br /&gt;
&lt;br /&gt;
==Kapazitive Sensoren==&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für kapazitive Sensoren sind Luftfeuchtigkeitsmesser, die ihre Kapazität entsprechend der Luftfeuchtigkeit ändern. Das Auslesen der Kapazität kann prinzipiell über das Ausmessen von Ladekurven geschehen. Dies ist jedoch bei kleinen Kapazitäten nicht praktisch durchführbar, weshalb man in diesem Falle meist einen Schwingkreis baut, dessen Frequenz man dann misst und so dann zusammen mit der bekannten Induktivität der Spule die Kapazität des Kondensators ausrechnen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:feuchtesensor.gif|framed|center|Valvo Feuchtigkeitssensor 10-90% (Kapazität: 122 pF bei TU = 25 °)]]&lt;br /&gt;
&lt;br /&gt;
==Induktive Sensoren==&lt;br /&gt;
Induktiver Näherungsschalter&lt;br /&gt;
&lt;br /&gt;
Sensoren die ihre Induktivität entsprechend der Messgröße ändern können auch mit Hilfe eines Schwingkreises mit bekannter Kapazität ausgemessen werden.&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
==Piezoelektrische Sensoren==&lt;br /&gt;
Hier ist ein Experiment dargestellt das die Funktion von Piezowandlern demonstriert.&lt;br /&gt;
&lt;br /&gt;
Drückt man auf eine längliche Glasplatte (Mikroskopträger Länge 76mm), die an den Enden auf je einem Piezo Wandler gelagert ist, dann ergeben sich Signale, die von den Kräften auf die Wandler abhängig sind. &lt;br /&gt;
&lt;br /&gt;
Die Summe der beiden Kräfte entspricht der Gesamtkraft. Das Verhältnis der beiden Kräfte entspricht dem Verhältnis der Abstände des Druckpunktes zum Wandler. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Piezowandler.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Versuch wurde mit der Frequenz von ca. 4Hz (0,5s/div) von einem Ende bis zum anderen auf die Platte gedrückt. (Tonleiter). Die Signale der beiden Wandler sind im Oszillogramm aufgetragen und die Folge der Druck-Positionen ist auf den ersten Blick schon mal nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
==PIR Passiv Infrarot Sensoren==&lt;br /&gt;
Hier handelt es sich um Passiv-Infrarot-Bewegungsmelder. Bewegungsmelder regieren beim Eintritt einer Person (Tier) in das Erfassungsfeld des Sensors. Die Anwendungsmöglichkeiten sind nahezu unbegrenzt, man kennt die Technik ja von vielen Terrassenlampen, welche sich beim vorbeigehen automatisch einschalten.&lt;br /&gt;
Reagiert wird also auf die Körperwärme einer sich im Erfassungsfeld bewegenden Person.&lt;br /&gt;
[[Bild:pir.jpg|right]]&lt;br /&gt;
Zum Prinzip: &lt;br /&gt;
Wärmestrahlen, die einen Erfassungsvorgang auslösen, liegen im Infrarot-Bereich des Wellenspektrums. In diesem Bereich gibt der menschliche Körper seine Wärmestrahlung ab. Leuchtmittel wie Glüh- , Halogen- und Entladungslampen, die für eine Strahlung im sichtbaren Bereich um 0,555 μm entwickelt wurden, geben jedoch auch einen erheblichen Teil an Wärmestrahlung im Infrarot-Bereich ab.&lt;br /&gt;
Im Spektrum oberhalb des sichtbaren Licht, ab 0,780 μm, beginnt der Infrarot-Bereich. Die Wellenlänge&lt;br /&gt;
dieser IR-Strahlung ist abhängig von der Temperatur eines Körpers. Die Wärmestrahlung&lt;br /&gt;
des Menschen hat ihr Maximum zwischen 9 und 10 μm im Infrarot-Bereich.&lt;br /&gt;
Diese Tatsache nutzt der PIR Sensor mittels sogenannter pyroelektrischer IRDetektoren, welche eine hohe Empfindlichkeit im langwelligen Infrarot-Bereich aufweisen. Die Infrarot-&lt;br /&gt;
Strahlung verhält sich ähnlich wie sichtbares Licht. Sie kann reflektiert und durch Linsen&lt;br /&gt;
gebündelt werden.&lt;br /&gt;
Basis eines solchen IR-Detektors (Sensors) sind Lithium-Tantalatkristalle. Diese Kristalle erzeugen,&lt;br /&gt;
bei Wärmeänderung (positive oder negative Temperaturänderung), eine elektrische Spannung.&lt;br /&gt;
Die von den Kristallen abgegebene Spannung liegt im Bereich von einigen μV (μV = millionstel Volt) und ist von folgenden Bedingungen abhängig: &lt;br /&gt;
* Der Intensität der Wärmequelle (Temperatur und Größe)&lt;br /&gt;
* Dem Umgebungsmedium (Temperatur, unterschiedliche Luftfeuchtigkeit)&lt;br /&gt;
* Der Entfernung zwischen Wärmequelle und IR-Sensor&lt;br /&gt;
* Der Bewegungsgeschwindigkeit und Bewegungsrichtung der Wärmequelle&lt;br /&gt;
* Der Empfindlichkeit des PIR-Elementes (frequenzabhängiges Bandpaßverhalten mit Maximum bei ca. 0,1 Hz)&lt;br /&gt;
&lt;br /&gt;
Zur Unterdrückung von Einflüssen aus der Umgebung (übliche wetterbedingte Temperaturänderungen), sind in jedem Sensor 2 Kristalle antiparallel geschaltet. &lt;br /&gt;
Einer der Kristalle gibt, bei Auftreffen von Wärmestrahlung einen positiven, der andere einen negativen Spannungsimpuls ab. Wärmeänderungen die gleichzeitig und mit gleicher Intensität auf beide Kristalle einwirken lösen so keinen Erfassungsvorgang aus, denn die beiden Impulse heben sich gegenseitig auf. Dadurch ist ein Auslösen bei Wärmeänderungen der Umgebung weitgehend ausgeschlossen.&lt;br /&gt;
Anders verhält es sich bei schnellen Bewegungen. Die Lithiumtantalat-Kristalle geben, entsprechend&lt;br /&gt;
der Bewegung und der dadurch hervorgerufenen Wärmeänderung im Erfassungsfeld, ihre&lt;br /&gt;
Impulse zeitversetzt ab. Die beiden Impulse addieren sich zu einer Wechselgröße mit höherer&lt;br /&gt;
Signalamplitude. Dieses elektrische Ausgangssignal ist proportional der Wärmeänderung und führt zur Meldung einer Bewegung.&lt;br /&gt;
&lt;br /&gt;
==Autoren==&lt;br /&gt;
* [[Benutzer:PicNick|PicNick]]&lt;br /&gt;
* [[Benutzer:Frank|Frank]] &lt;br /&gt;
* [[Benutzer:Dennis.strehl|Dennis.strehl]]&lt;br /&gt;
* [[Benutzer:Florian|Florian]]&lt;br /&gt;
* [[Benutzer:BASTIUniversal|BASTIUniversal]]&lt;br /&gt;
* Topic&lt;br /&gt;
* [[Benutzer:Manf|Manf]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[Navigation]]&lt;br /&gt;
* [[Sensoren]]&lt;br /&gt;
* [[Graycode]]&lt;br /&gt;
* [[Ultraschall SRF10 an RN-Control]]&lt;br /&gt;
* [[Ultraschall SRF05 an RN-MiniControl]]&lt;br /&gt;
* [[Ultraschallsensor SRF02 am RN-Board]]&lt;br /&gt;
* [[Bascom und Kompass CMPS03]]&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
*[http://www.ikm.uni-karlsruhe.de/forschung/pzt_webseiten/de/grundlagen/pyro.html Piezoelektrische Sensoren]&lt;br /&gt;
*[http://www.roboternetz.de/phpBB2/dload.php?action=category&amp;amp;cat_id=2 Datenblätter im Download-Bereich des Roboternetz]&lt;br /&gt;
*[http://www.nxp.com/acrobat_download/various/SC17_GENERAL_TEMP_1996_3.pdf KTY Sensor Datenblatt]&lt;br /&gt;
*[http://www.tranzistoare.ro/datasheets2/83/83853_1.pdf NTC Datenblatt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Robotikeinstieg]]&lt;br /&gt;
[[Category:Grundlagen]]&lt;br /&gt;
[[Category:Elektronik]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=14947</id>
		<title>Programmer</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=14947"/>
				<updated>2009-05-23T17:19:06Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Weblinks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Als '''Programmer''' bezeichnet wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des &amp;quot;serial Download&amp;quot; eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen &amp;quot;Standard&amp;quot; [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen &amp;quot;billig&amp;quot; Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene &amp;quot;Intelligenz&amp;quot; verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.&lt;br /&gt;
&lt;br /&gt;
== Parallelport ISP Programmer ==&lt;br /&gt;
&lt;br /&gt;
=== STK 200 kompatible Programmer ===&lt;br /&gt;
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. &lt;br /&gt;
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. &lt;br /&gt;
&lt;br /&gt;
 LPT-Pinning des STK200&lt;br /&gt;
 SCK   = 6;&lt;br /&gt;
 MOSI  = 7;&lt;br /&gt;
 RESET = 9;&lt;br /&gt;
 MISO  = 10;&lt;br /&gt;
&lt;br /&gt;
=== SP12 kompatible Programmer ===&lt;br /&gt;
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. &lt;br /&gt;
 &lt;br /&gt;
 LPT-Pinning des SP12&lt;br /&gt;
 VCC   = 4,5,6,7,8;&lt;br /&gt;
 RESET = 3;&lt;br /&gt;
 SCK   = 2;&lt;br /&gt;
 MOSI  = 9;&lt;br /&gt;
 MISO  = 11;&lt;br /&gt;
&lt;br /&gt;
== Pseudo serielle Programmer (SI-Prog) ==&lt;br /&gt;
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Echte serielle Programmer ==&lt;br /&gt;
Echte serielle Programmer basieren entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) empfindlich kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und es kann diese mit einem handelsüblichen USB-Serial-Adapter auch an Systemen betrieben werden, die, wie viele Notebooks heute, nur noch über USB verfügen. Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
== USB Programmer ==&lt;br /&gt;
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für billige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab).  Das USB interface ist allerdings wohl nicht 100% normconform und es könnte dadurch zu Inkompatibilitäten kommen.&lt;br /&gt;
&lt;br /&gt;
== ISP-Anschluss ==&lt;br /&gt;
&lt;br /&gt;
=== 10poliger ISP Anschluss ===&lt;br /&gt;
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.&lt;br /&gt;
&lt;br /&gt;
 1 - MOSI&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - LED (oft auch unbelegt)&lt;br /&gt;
 4 - GND&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
 7 - SCK&lt;br /&gt;
 8 - GND&lt;br /&gt;
 9 - MISO&lt;br /&gt;
 10 - GND&lt;br /&gt;
&lt;br /&gt;
=== 6poliger ISP Anschluss ===&lt;br /&gt;
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber deutlich schwieriger (und teurer) zu bekommen als die zehnpolige Variante.  &lt;br /&gt;
 1 - MISO&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - SCK&lt;br /&gt;
 4 - MOSI&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
&lt;br /&gt;
== Autor ==&lt;br /&gt;
*[[Benutzer:Martin Fiedler|Martin Fiedler]]&lt;br /&gt;
*Kleinere Änderungen Frank&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP&lt;br /&gt;
* [[ISP]]&lt;br /&gt;
* [[RN-Definitionen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]&lt;br /&gt;
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]&lt;br /&gt;
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.&lt;br /&gt;
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung&lt;br /&gt;
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]&lt;br /&gt;
* [http://shop.embedit.de/browse_030001002_66__.php embedit.de] Bezugsquelle für sechspoligen Stecker&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=14946</id>
		<title>Programmer</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=14946"/>
				<updated>2009-05-23T17:17:58Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Weblinks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Als '''Programmer''' bezeichnet wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des &amp;quot;serial Download&amp;quot; eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen &amp;quot;Standard&amp;quot; [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen &amp;quot;billig&amp;quot; Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene &amp;quot;Intelligenz&amp;quot; verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.&lt;br /&gt;
&lt;br /&gt;
== Parallelport ISP Programmer ==&lt;br /&gt;
&lt;br /&gt;
=== STK 200 kompatible Programmer ===&lt;br /&gt;
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. &lt;br /&gt;
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. &lt;br /&gt;
&lt;br /&gt;
 LPT-Pinning des STK200&lt;br /&gt;
 SCK   = 6;&lt;br /&gt;
 MOSI  = 7;&lt;br /&gt;
 RESET = 9;&lt;br /&gt;
 MISO  = 10;&lt;br /&gt;
&lt;br /&gt;
=== SP12 kompatible Programmer ===&lt;br /&gt;
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. &lt;br /&gt;
 &lt;br /&gt;
 LPT-Pinning des SP12&lt;br /&gt;
 VCC   = 4,5,6,7,8;&lt;br /&gt;
 RESET = 3;&lt;br /&gt;
 SCK   = 2;&lt;br /&gt;
 MOSI  = 9;&lt;br /&gt;
 MISO  = 11;&lt;br /&gt;
&lt;br /&gt;
== Pseudo serielle Programmer (SI-Prog) ==&lt;br /&gt;
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Echte serielle Programmer ==&lt;br /&gt;
Echte serielle Programmer basieren entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) empfindlich kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und es kann diese mit einem handelsüblichen USB-Serial-Adapter auch an Systemen betrieben werden, die, wie viele Notebooks heute, nur noch über USB verfügen. Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
== USB Programmer ==&lt;br /&gt;
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für billige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab).  Das USB interface ist allerdings wohl nicht 100% normconform und es könnte dadurch zu Inkompatibilitäten kommen.&lt;br /&gt;
&lt;br /&gt;
== ISP-Anschluss ==&lt;br /&gt;
&lt;br /&gt;
=== 10poliger ISP Anschluss ===&lt;br /&gt;
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.&lt;br /&gt;
&lt;br /&gt;
 1 - MOSI&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - LED (oft auch unbelegt)&lt;br /&gt;
 4 - GND&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
 7 - SCK&lt;br /&gt;
 8 - GND&lt;br /&gt;
 9 - MISO&lt;br /&gt;
 10 - GND&lt;br /&gt;
&lt;br /&gt;
=== 6poliger ISP Anschluss ===&lt;br /&gt;
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber deutlich schwieriger (und teurer) zu bekommen als die zehnpolige Variante.  &lt;br /&gt;
 1 - MISO&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - SCK&lt;br /&gt;
 4 - MOSI&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
&lt;br /&gt;
== Autor ==&lt;br /&gt;
*[[Benutzer:Martin Fiedler|Martin Fiedler]]&lt;br /&gt;
*Kleinere Änderungen Frank&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP&lt;br /&gt;
* [[ISP]]&lt;br /&gt;
* [[RN-Definitionen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]&lt;br /&gt;
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]&lt;br /&gt;
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.&lt;br /&gt;
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung&lt;br /&gt;
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]&lt;br /&gt;
* [http://shop.embedit.de/browse_030001002_66__.php#embedit.de] Bezugsquelle für sechspoligen Stecker&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=14945</id>
		<title>Programmer</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Programmer&amp;diff=14945"/>
				<updated>2009-05-23T17:17:11Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Weblinks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Als '''Programmer''' bezeichnet wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des &amp;quot;serial Download&amp;quot; eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen &amp;quot;Standard&amp;quot; [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen &amp;quot;billig&amp;quot; Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene &amp;quot;Intelligenz&amp;quot; verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.&lt;br /&gt;
&lt;br /&gt;
== Parallelport ISP Programmer ==&lt;br /&gt;
&lt;br /&gt;
=== STK 200 kompatible Programmer ===&lt;br /&gt;
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. &lt;br /&gt;
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. &lt;br /&gt;
&lt;br /&gt;
 LPT-Pinning des STK200&lt;br /&gt;
 SCK   = 6;&lt;br /&gt;
 MOSI  = 7;&lt;br /&gt;
 RESET = 9;&lt;br /&gt;
 MISO  = 10;&lt;br /&gt;
&lt;br /&gt;
=== SP12 kompatible Programmer ===&lt;br /&gt;
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. &lt;br /&gt;
 &lt;br /&gt;
 LPT-Pinning des SP12&lt;br /&gt;
 VCC   = 4,5,6,7,8;&lt;br /&gt;
 RESET = 3;&lt;br /&gt;
 SCK   = 2;&lt;br /&gt;
 MOSI  = 9;&lt;br /&gt;
 MISO  = 11;&lt;br /&gt;
&lt;br /&gt;
== Pseudo serielle Programmer (SI-Prog) ==&lt;br /&gt;
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Echte serielle Programmer ==&lt;br /&gt;
Echte serielle Programmer basieren entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) empfindlich kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und es kann diese mit einem handelsüblichen USB-Serial-Adapter auch an Systemen betrieben werden, die, wie viele Notebooks heute, nur noch über USB verfügen. Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
== USB Programmer ==&lt;br /&gt;
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für billige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab).  Das USB interface ist allerdings wohl nicht 100% normconform und es könnte dadurch zu Inkompatibilitäten kommen.&lt;br /&gt;
&lt;br /&gt;
== ISP-Anschluss ==&lt;br /&gt;
&lt;br /&gt;
=== 10poliger ISP Anschluss ===&lt;br /&gt;
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.&lt;br /&gt;
&lt;br /&gt;
 1 - MOSI&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - LED (oft auch unbelegt)&lt;br /&gt;
 4 - GND&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
 7 - SCK&lt;br /&gt;
 8 - GND&lt;br /&gt;
 9 - MISO&lt;br /&gt;
 10 - GND&lt;br /&gt;
&lt;br /&gt;
=== 6poliger ISP Anschluss ===&lt;br /&gt;
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber deutlich schwieriger (und teurer) zu bekommen als die zehnpolige Variante.  &lt;br /&gt;
 1 - MISO&lt;br /&gt;
 2 - VCC&lt;br /&gt;
 3 - SCK&lt;br /&gt;
 4 - MOSI&lt;br /&gt;
 5 - RST&lt;br /&gt;
 6 - GND&lt;br /&gt;
&lt;br /&gt;
== Autor ==&lt;br /&gt;
*[[Benutzer:Martin Fiedler|Martin Fiedler]]&lt;br /&gt;
*Kleinere Änderungen Frank&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP&lt;br /&gt;
* [[ISP]]&lt;br /&gt;
* [[RN-Definitionen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]&lt;br /&gt;
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]&lt;br /&gt;
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.&lt;br /&gt;
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]&lt;br /&gt;
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung&lt;br /&gt;
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]&lt;br /&gt;
* [http://shop.embedit.de/browse_030001002_66__.php] Bezugsquelle für sechspoligen Stecker&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=14911</id>
		<title>Roboterwettbewerbe</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=14911"/>
				<updated>2009-05-09T21:20:28Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* RobotLiga */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf diese Seite werden die bekanntesten nationalen und internationalen Roboterwettbewerbe kurz vorgestellt.&lt;br /&gt;
&lt;br /&gt;
==Überblick==&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |''' Wettbewerb primär für'''||Schüler ||Studenten || Hobbyrobotiker ||1 Person || bis 5 Personen || mehr als 5 Personen &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Eurobot|Eurobot]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#FIRST_Lego_League|First Lego Leaue]] || X ||  ||  || || X ||    &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboChallenge (findet vorerst nicht mehr statt) || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboCup_Soccer|RoboCup Soccer]] || || X ||  ||  ||  || X  &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboCup Junior || X || || || || X || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboKing|RoboKing]] || X || || || || X ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotChallenge|RobotChallenge]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotLiga|RobotLiga]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboTest|RoboTest]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#SPURT|SPURT]] || X || || ||  || X || &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ELROB|European Land Robot Trial (ELROB)]] ||  || X ||  || ||  || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#GSF_Robot_Contest|GSF Robot Contest]] ||  ||  || X ||X || X ||  &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ROBOCOM|ROBOCOM]] || X ||  ||  ||  || X ||&lt;br /&gt;
&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
==Eurobot==&lt;br /&gt;
&amp;quot;Seit 1998 ist Eurobot ein internationaler Roboterwettbewerb für Teams von Jugendlichen, Studenten und sonstigen an Robotern interessierten Menschen.&lt;br /&gt;
Eurobot findet stets in Europa statt, ist aber für alle Länder aller Kontinente zugänglich. Im Jahre 2004 nahmen insgesamt 250 Teams aus 21 Länder an diesem technisch/wissenschaftlichen Wettbewerb teil.&amp;quot; (zitiert von www.eurobot.org)&lt;br /&gt;
Aus jedem Land dürfen maximal drei Teams zu den internationalen Finalen fahren. Diese drei Mannschaften müssen sich in nationalen Vorausscheiden qualifizieren. Die Aufgabe wird jedes Jahr neu gestellt. Nur die Rahmenbedingungen bleiben gleich: Ein Match dauert nur 90 Sekunden, es ist also sowohl Schnelligkeit als auch eine intelligente Taktik und Sicherheit gefragt. Die Spielfläche ist etwa 2x3 Meter groß.&lt;br /&gt;
Eurobot findet seit 2005 jedes Jahr in einem anderen Land statt. Der Wettbewerb wird von einer großen Rahmenveranstaltung inklusive Vorträgen und vielen Attraktionen für die zahlreichen Zuschauer ergänzt.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.eurobot.org www.eurobot.org]&lt;br /&gt;
* [http://www.eurobot-deutschland.de www.eurobot-deutschland.de]&lt;br /&gt;
&lt;br /&gt;
==FIRST Lego League==&lt;br /&gt;
Bei der First Lego League handelt es sich um einen Wettbewerb der von den Firmen Lego und FIRST veranstalltet wird. Er findet jährlich auf der ganzen Welt mit regional Runden statt. Hierzu werden jedes Jahr an interressierte Gruppen die Aufgaben, wie die dafür benötigten Aufbauten aus Lego verschickt. &lt;br /&gt;
Bei diesem Wettbewerb dürfen nur Roboter eingesetzt werden, die aus dem LEGO Mindstorms System bestehen. Der Wettbewerb richtet sich vornehmlich an junge Schüler, wie auch das gesamte Mindstorms System. Deshalb dürfen die Teilnehmer auch maximal 16 Jahre alt sein. Jedes Team benötigt einen Volljährigen Coach, der dem Team bei der Bewältigung der Aufgaben hilft.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.firstlegoleague.org/ www.firstlegoleague.org]&lt;br /&gt;
&lt;br /&gt;
==RoboCup Soccer==&lt;br /&gt;
Die Komplexität und Beliebtheit von Fußball (soccer) spielten wesentliche Rollen bei der Motivation der ersten RoboCupspiele Mitte der 90er Jahre. Die Dynamik und die Komplexität von Fußball birgt enorme Herausforderungen für Wissenschaftler, die sich mit der Entwicklung von autonomen Robotern in diesem Bereich beschäftigen: &lt;br /&gt;
&lt;br /&gt;
Individuelle Herausforderungen: jeder Agent/Roboter muss Objekte erkennen, sich selbst lokalisieren, navigieren und den Ball bewegen können. Zu klären sind Fragen wie: was ist in diesem Moment wichtig in meiner Wahrnehmung? Ist meine Position und die der anderen Mitspieler bekannt? &lt;br /&gt;
Kooperation von Agenten: in einer dynamischen Echtzeitumgebung kommt es nicht auf einen einzelnen Spieler an, sondern besonders auf das kooperative Spiel, bei dem auch die Kommunikation eine große Rolle spielt.&lt;br /&gt;
&lt;br /&gt;
Dynamische Echtzeitumgebung mit sich bewegenden Objekten, von denen einige intelligente Agenten sind, die gegen einen spielen. Diese Art von Umgebung ist z.B. auch im Straßenverkehr zu beobachten, wobei die anderen Verkehrsteilnehmer zwar keine Gegner sind, die meine Pläne durchkreuzen wollen, wo aber die Situationen beliebig komplex werden können.&lt;br /&gt;
RoboCupSoccer besteht aus fünf Ligen: der Simulationsliga, der Small-Size Liga, der Middle-Size Liga, der Sony Legged Liga, und der Humanoidliga. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robocup.org www.robocup.org]&lt;br /&gt;
&lt;br /&gt;
==RoboKing==&lt;br /&gt;
RoboKing ist ein Wettbewerb für technikinteressierte Schüler, der jährlich von der TU Chemnitz organisiert wird. Jedes Team besteht aus 3 bis 5 Schülern und einem erwachsenem Teamleiter. RoboKing richtet sich ausdrücklich auch an Schülergruppen ohne große Vorkenntnisse. Ziel der Initiative ist, Schüler für ein Studium ingenieurwissenschaftlicher Fächer zu begeistern und zu zeigen, dass auch Schulfächer wie Physik und Informatik eine Menge Spaß machen können. Das Durchschnittsalter der Teilnehmer liegt bei etwa 16 Jahren. Die jüngsten Teilnehmer waren 10 Jahre alt. &lt;br /&gt;
&lt;br /&gt;
Besonderes Highlight des Wettberwebs RoboKing ist zweifellos eine Gutschrift, von denen die Teilnehmer alle Materialien die zum Bau des Roboters benötigt werden, bezahlen können. Dadurch unterscheidet sich dieser Wettbewerb von allen vergleichbaren, denn auf die teilnehmenden Schüler kommen keine Kosten für Material zu. Jedes Jahr werden 25 Teams mit dieser Gutschrift finanziell unterstützt. Ab dem Wettbewerb RoboKing 2007 (startet im Frühjahr 2006) können zusätzlich auch alle Teams teilnehmen, die sich selbst finanzieren.&lt;br /&gt;
&lt;br /&gt;
Die Endrunde des Wettbewerbs wurde 2004 und auf der Hannover Messe ausgetragen. 2006 fand das Finale auf der digital living / CeBIT statt.&lt;br /&gt;
Eine weitere Besonderheit des Wettbewerbs: Jedes Jahr müssen die Teilnehmer eine andere Aufgabenstellung lösen.  Bei den vergangenen Wettbewerben mussten die Roboter sicher durch ein großes Labyrinth navigieren, Tennisbälle einsammeln und in die eigene Basis bringen oder Bauklötzchen durch einen Hindernisparcours mit Graben, Brücke und Schlucht transportieren. Die Teilnehmer haben nach Bekanntgabe der Spielregeln etwa 8 Monate Zeit, die Aufgabe zu lösen.&lt;br /&gt;
&lt;br /&gt;
RoboKing finanziert sich ausschließlich über Spenden von zahlreichen Sponsoren. Verantwortlich für die Organisation sind die Mitarbeiter und Studenten der Professur Prozessautomatisierung der TU Chemnitz.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.roboking.de www.roboking.de]&lt;br /&gt;
&lt;br /&gt;
==RobotChallenge==&lt;br /&gt;
Die RobotChallenge ist ein österreichischer Wettbewerb für selbstgebaute, autonome Roboter, dessen Ziel es ist für den kreativen Umgang mit innovativen Technologien zu begeistern. Experimente und praktische Erfahrungen lassen Teilnehmer und Zuschauer Wissenschaft hautnah erleben. Dieser Wettbewerb soll zeigen, wie man mit einfachen Mitteln, aber offenem Geiste und Phantasie spannende, zukunftstaugliche Lösungen finden kann. &lt;br /&gt;
Folgende Disiplienen wurden dort schon ausgetragen:&lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom'''&amp;lt;br&amp;gt;&lt;br /&gt;
Möglichst schnell muss einer schwarzen Linie auf weißem Untergrund entlang gefahren werden. Reglement im Wesentlichen wie bei RC'05. &lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom Enhanced'''&amp;lt;br&amp;gt;&lt;br /&gt;
Wie Parallel-Slalom, jedoch mit Erschwernissen: ein Tunnel, eine kurze Unterbrechung der Linie und ein Hindernis auf der Linie, das umfahren werden muss. &lt;br /&gt;
&lt;br /&gt;
'''Robot-Sumo'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter treten gegeneinander an und versuchen den jeweils anderen von einer runden Platte zu schieben. Die Platte ist schwarz, der Rand ist durch einen weissen Streifen markiert. Die Regeln entsprechen der internationalen Norm für autonomes Roboter-Sumo. &lt;br /&gt;
&lt;br /&gt;
'''Hindernislauf'''&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Infrarot-Leuchtturm mit definiertem Signal am Ende des Parcours ist möglichst rasch zu erreichen. Auf dem Weg befindliche Hindernisse müssen umfahren werden. Jedes Team kann alternativ auch einen eigenen Leuchtturm als Orientierungshilfe mitbringen. Reglement im Wesentlichen wie bei RC'05, jedoch sind auch komplexere Hindernisse (z.B. Sackgassen) möglich. &lt;br /&gt;
&lt;br /&gt;
'''Puck Collect'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter - von denen einem die Farbe rot, dem anderen blau zugeteilt wird - treten gegeneinander an. Auf dem Spielfeld sind kleine rote und blaue Scheiben (Pucks) verteilt. Ziel ist es, möglichst schnell alle Pucks der eigenen Farbe einzusammeln und zur eigenen, farblich gekennzeichneten Homebase zu bringen. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotchallenge.at/ RobotChallenge]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==RobotLiga==&lt;br /&gt;
Die RobotLiga findet in Kaiserslautern statt. Der nächste Termin ist noch nicht bekannt. Teilnehmen können alle interessierten Roboterbastler.&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 75cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotliga.de/ RobotLiga]&lt;br /&gt;
&lt;br /&gt;
==RoboTest==&lt;br /&gt;
Veranstaltungsort: Bei Frankfurt am Main&lt;br /&gt;
&lt;br /&gt;
Nächster Termin: voraussichtlich im Herbst 2009&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2 bis 3cm breit. Es starten immer zwei Roboter gleichzeitig in einem Parallelslalom. Der Wettbewerb läuft in mehreren Runden nach dem KO-System. &lt;br /&gt;
&lt;br /&gt;
'''BLOCKED LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Auf der Strecke stehen Hindernisse, die umfahren werden müssen. &lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2 bis 5cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, innerhalb von drei Minuten möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MICRO LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen für sehr kleine Roboter. Die maximale Größe liegt bei 8x8x8cm und 200g. Je kleiner und leichter der Roboter ist, desto mehr Bonuspunkte gibt es.  &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''JUST WALK'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 1m zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://WWW.ROBOTEST.DE/ RoboTest]&lt;br /&gt;
&lt;br /&gt;
==SPURT==&lt;br /&gt;
Der Wettbewerb SPURT (die Abkürzung steht für &amp;quot;Schüler-Projekte um Roboter-Technik&amp;quot;) wird jährlich von der Universität Rostock veranstaltet. SPURT richtet sich an technikinteressierte Schüler. Die zu lösende Aufgabe ist eine Linienverfolgung. Wer am schnellsten die herzförmige Linie abfährt, hat gewonnen.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://spurt.uni-rostock.de/ Wettbewerb SPURT]&lt;br /&gt;
&lt;br /&gt;
==ELROB==&lt;br /&gt;
Die deutsche Bundeswehr möchte Firma und Privatpersonen einladen, am European Land-Robot Trial 2006 (ELROB 2006) teilzunehmen.  Die ELROB wird veranstaltet, um einen Überblick über den europäischen State-of-the-art auf dem Gebiet von UGVs (unmanned ground vehicles) mit Fokus auf kurzfristig realisierbare Robotersystemen zu liefern.  Hinsichtlich der vorhandenen Fähigkeiten versuchen die Organisatoren, technische Lösungen zu fördern, die den Betrieb unbemannter Fahrzeuge (UGV) verbessern.  Repräsentanten aus Militär, Grenzschutz, Spezialkräften, Polizei, Feuerwehr, und Zivilschutzagenturen aus vielen europäischen Ländern werden anwesend sein.  Die ELROB wird von einer Ausstellung begleitet, welche eine breite Vielzahl an Robotikaspekten umfasst.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.elrob2006.org/ Wettbewerb ELROB 2006]&lt;br /&gt;
&lt;br /&gt;
==GSF Robot Contest==&lt;br /&gt;
Ein neuer Wettbewerb für Hobbyrobotiker. Er findet am 19.5.07 erstmals statt. Austragunsordt ist Fröndenberg (Raum Dortmund/Unna).&lt;br /&gt;
Die Aufgaben sind teilweise angelehnt an die der RobotLiga.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegenrische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Naqch einem akustischen &amp;quot;Feueralarm&amp;quot; muss eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude gefunden und gelöscht werden. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinader an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 100cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREESTYLE'''&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Disziplin hat jeder Teilnehmer die Möglichkeit seinen Roboter vorzustellen und zu zeigen was dieser kann.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www.gsf-robot-contest.de/&lt;br /&gt;
&lt;br /&gt;
==ROBOCOM==&lt;br /&gt;
Bei diesem Wettbewerb soll eine vorgegebene Aufgabe mit LEGO MINDSTORMS NXT Robotern autonom, d.h. ohne Eingriffe von außen bewältigt werden. Mit diesem Wettbewerb möchte die Fachhochschule Gelsenkirchen in den Schulen den Einsatz moderner Techniken fördern und Schülerinnen und Schüler für ein naturwissenschaftliches Studium interessieren.&amp;lt;br&amp;gt;&lt;br /&gt;
Am 15.06.2007 fand der Schülerwettbewerb ROBOCOM2007 zum erstem Mal statt. Am 26.06.2009 veranstaltet die Fachhochschule Gelsenkirchen die ROBOCOM2009.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www2.fh-gelsenkirchen.de/FH-Sites/FB1/index.php?id=791&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Praxis]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=14910</id>
		<title>Roboterwettbewerbe</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Roboterwettbewerbe&amp;diff=14910"/>
				<updated>2009-05-09T21:19:41Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* RoboTest */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf diese Seite werden die bekanntesten nationalen und internationalen Roboterwettbewerbe kurz vorgestellt.&lt;br /&gt;
&lt;br /&gt;
==Überblick==&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |''' Wettbewerb primär für'''||Schüler ||Studenten || Hobbyrobotiker ||1 Person || bis 5 Personen || mehr als 5 Personen &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#Eurobot|Eurobot]] || || X || || || || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#FIRST_Lego_League|First Lego Leaue]] || X ||  ||  || || X ||    &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboChallenge (findet vorerst nicht mehr statt) || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboCup_Soccer|RoboCup Soccer]] || || X ||  ||  ||  || X  &lt;br /&gt;
 |-&lt;br /&gt;
 |RoboCup Junior || X || || || || X || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboKing|RoboKing]] || X || || || || X ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotChallenge|RobotChallenge]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RobotLiga|RobotLiga]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#RoboTest|RoboTest]] || || || X || X || ||&lt;br /&gt;
 |-&lt;br /&gt;
 |[[#SPURT|SPURT]] || X || || ||  || X || &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ELROB|European Land Robot Trial (ELROB)]] ||  || X ||  || ||  || X &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#GSF_Robot_Contest|GSF Robot Contest]] ||  ||  || X ||X || X ||  &lt;br /&gt;
 |-&lt;br /&gt;
 |[[#ROBOCOM|ROBOCOM]] || X ||  ||  ||  || X ||&lt;br /&gt;
&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
==Eurobot==&lt;br /&gt;
&amp;quot;Seit 1998 ist Eurobot ein internationaler Roboterwettbewerb für Teams von Jugendlichen, Studenten und sonstigen an Robotern interessierten Menschen.&lt;br /&gt;
Eurobot findet stets in Europa statt, ist aber für alle Länder aller Kontinente zugänglich. Im Jahre 2004 nahmen insgesamt 250 Teams aus 21 Länder an diesem technisch/wissenschaftlichen Wettbewerb teil.&amp;quot; (zitiert von www.eurobot.org)&lt;br /&gt;
Aus jedem Land dürfen maximal drei Teams zu den internationalen Finalen fahren. Diese drei Mannschaften müssen sich in nationalen Vorausscheiden qualifizieren. Die Aufgabe wird jedes Jahr neu gestellt. Nur die Rahmenbedingungen bleiben gleich: Ein Match dauert nur 90 Sekunden, es ist also sowohl Schnelligkeit als auch eine intelligente Taktik und Sicherheit gefragt. Die Spielfläche ist etwa 2x3 Meter groß.&lt;br /&gt;
Eurobot findet seit 2005 jedes Jahr in einem anderen Land statt. Der Wettbewerb wird von einer großen Rahmenveranstaltung inklusive Vorträgen und vielen Attraktionen für die zahlreichen Zuschauer ergänzt.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.eurobot.org www.eurobot.org]&lt;br /&gt;
* [http://www.eurobot-deutschland.de www.eurobot-deutschland.de]&lt;br /&gt;
&lt;br /&gt;
==FIRST Lego League==&lt;br /&gt;
Bei der First Lego League handelt es sich um einen Wettbewerb der von den Firmen Lego und FIRST veranstalltet wird. Er findet jährlich auf der ganzen Welt mit regional Runden statt. Hierzu werden jedes Jahr an interressierte Gruppen die Aufgaben, wie die dafür benötigten Aufbauten aus Lego verschickt. &lt;br /&gt;
Bei diesem Wettbewerb dürfen nur Roboter eingesetzt werden, die aus dem LEGO Mindstorms System bestehen. Der Wettbewerb richtet sich vornehmlich an junge Schüler, wie auch das gesamte Mindstorms System. Deshalb dürfen die Teilnehmer auch maximal 16 Jahre alt sein. Jedes Team benötigt einen Volljährigen Coach, der dem Team bei der Bewältigung der Aufgaben hilft.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks''':&lt;br /&gt;
* [http://www.firstlegoleague.org/ www.firstlegoleague.org]&lt;br /&gt;
&lt;br /&gt;
==RoboCup Soccer==&lt;br /&gt;
Die Komplexität und Beliebtheit von Fußball (soccer) spielten wesentliche Rollen bei der Motivation der ersten RoboCupspiele Mitte der 90er Jahre. Die Dynamik und die Komplexität von Fußball birgt enorme Herausforderungen für Wissenschaftler, die sich mit der Entwicklung von autonomen Robotern in diesem Bereich beschäftigen: &lt;br /&gt;
&lt;br /&gt;
Individuelle Herausforderungen: jeder Agent/Roboter muss Objekte erkennen, sich selbst lokalisieren, navigieren und den Ball bewegen können. Zu klären sind Fragen wie: was ist in diesem Moment wichtig in meiner Wahrnehmung? Ist meine Position und die der anderen Mitspieler bekannt? &lt;br /&gt;
Kooperation von Agenten: in einer dynamischen Echtzeitumgebung kommt es nicht auf einen einzelnen Spieler an, sondern besonders auf das kooperative Spiel, bei dem auch die Kommunikation eine große Rolle spielt.&lt;br /&gt;
&lt;br /&gt;
Dynamische Echtzeitumgebung mit sich bewegenden Objekten, von denen einige intelligente Agenten sind, die gegen einen spielen. Diese Art von Umgebung ist z.B. auch im Straßenverkehr zu beobachten, wobei die anderen Verkehrsteilnehmer zwar keine Gegner sind, die meine Pläne durchkreuzen wollen, wo aber die Situationen beliebig komplex werden können.&lt;br /&gt;
RoboCupSoccer besteht aus fünf Ligen: der Simulationsliga, der Small-Size Liga, der Middle-Size Liga, der Sony Legged Liga, und der Humanoidliga. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robocup.org www.robocup.org]&lt;br /&gt;
&lt;br /&gt;
==RoboKing==&lt;br /&gt;
RoboKing ist ein Wettbewerb für technikinteressierte Schüler, der jährlich von der TU Chemnitz organisiert wird. Jedes Team besteht aus 3 bis 5 Schülern und einem erwachsenem Teamleiter. RoboKing richtet sich ausdrücklich auch an Schülergruppen ohne große Vorkenntnisse. Ziel der Initiative ist, Schüler für ein Studium ingenieurwissenschaftlicher Fächer zu begeistern und zu zeigen, dass auch Schulfächer wie Physik und Informatik eine Menge Spaß machen können. Das Durchschnittsalter der Teilnehmer liegt bei etwa 16 Jahren. Die jüngsten Teilnehmer waren 10 Jahre alt. &lt;br /&gt;
&lt;br /&gt;
Besonderes Highlight des Wettberwebs RoboKing ist zweifellos eine Gutschrift, von denen die Teilnehmer alle Materialien die zum Bau des Roboters benötigt werden, bezahlen können. Dadurch unterscheidet sich dieser Wettbewerb von allen vergleichbaren, denn auf die teilnehmenden Schüler kommen keine Kosten für Material zu. Jedes Jahr werden 25 Teams mit dieser Gutschrift finanziell unterstützt. Ab dem Wettbewerb RoboKing 2007 (startet im Frühjahr 2006) können zusätzlich auch alle Teams teilnehmen, die sich selbst finanzieren.&lt;br /&gt;
&lt;br /&gt;
Die Endrunde des Wettbewerbs wurde 2004 und auf der Hannover Messe ausgetragen. 2006 fand das Finale auf der digital living / CeBIT statt.&lt;br /&gt;
Eine weitere Besonderheit des Wettbewerbs: Jedes Jahr müssen die Teilnehmer eine andere Aufgabenstellung lösen.  Bei den vergangenen Wettbewerben mussten die Roboter sicher durch ein großes Labyrinth navigieren, Tennisbälle einsammeln und in die eigene Basis bringen oder Bauklötzchen durch einen Hindernisparcours mit Graben, Brücke und Schlucht transportieren. Die Teilnehmer haben nach Bekanntgabe der Spielregeln etwa 8 Monate Zeit, die Aufgabe zu lösen.&lt;br /&gt;
&lt;br /&gt;
RoboKing finanziert sich ausschließlich über Spenden von zahlreichen Sponsoren. Verantwortlich für die Organisation sind die Mitarbeiter und Studenten der Professur Prozessautomatisierung der TU Chemnitz.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.roboking.de www.roboking.de]&lt;br /&gt;
&lt;br /&gt;
==RobotChallenge==&lt;br /&gt;
Die RobotChallenge ist ein österreichischer Wettbewerb für selbstgebaute, autonome Roboter, dessen Ziel es ist für den kreativen Umgang mit innovativen Technologien zu begeistern. Experimente und praktische Erfahrungen lassen Teilnehmer und Zuschauer Wissenschaft hautnah erleben. Dieser Wettbewerb soll zeigen, wie man mit einfachen Mitteln, aber offenem Geiste und Phantasie spannende, zukunftstaugliche Lösungen finden kann. &lt;br /&gt;
Folgende Disiplienen wurden dort schon ausgetragen:&lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom'''&amp;lt;br&amp;gt;&lt;br /&gt;
Möglichst schnell muss einer schwarzen Linie auf weißem Untergrund entlang gefahren werden. Reglement im Wesentlichen wie bei RC'05. &lt;br /&gt;
&lt;br /&gt;
'''Parallel-Slalom Enhanced'''&amp;lt;br&amp;gt;&lt;br /&gt;
Wie Parallel-Slalom, jedoch mit Erschwernissen: ein Tunnel, eine kurze Unterbrechung der Linie und ein Hindernis auf der Linie, das umfahren werden muss. &lt;br /&gt;
&lt;br /&gt;
'''Robot-Sumo'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter treten gegeneinander an und versuchen den jeweils anderen von einer runden Platte zu schieben. Die Platte ist schwarz, der Rand ist durch einen weissen Streifen markiert. Die Regeln entsprechen der internationalen Norm für autonomes Roboter-Sumo. &lt;br /&gt;
&lt;br /&gt;
'''Hindernislauf'''&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Infrarot-Leuchtturm mit definiertem Signal am Ende des Parcours ist möglichst rasch zu erreichen. Auf dem Weg befindliche Hindernisse müssen umfahren werden. Jedes Team kann alternativ auch einen eigenen Leuchtturm als Orientierungshilfe mitbringen. Reglement im Wesentlichen wie bei RC'05, jedoch sind auch komplexere Hindernisse (z.B. Sackgassen) möglich. &lt;br /&gt;
&lt;br /&gt;
'''Puck Collect'''&amp;lt;br&amp;gt;&lt;br /&gt;
Je zwei Roboter - von denen einem die Farbe rot, dem anderen blau zugeteilt wird - treten gegeneinander an. Auf dem Spielfeld sind kleine rote und blaue Scheiben (Pucks) verteilt. Ziel ist es, möglichst schnell alle Pucks der eigenen Farbe einzusammeln und zur eigenen, farblich gekennzeichneten Homebase zu bringen. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotchallenge.at/ RobotChallenge]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==RobotLiga==&lt;br /&gt;
Die RobotLiga findet in Kaiserslautern statt. Der nächste Termin ist der 17.11.07. Teilnehmen können alle interessierten Roboterbastler.&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 75cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.robotliga.de/ RobotLiga]&lt;br /&gt;
&lt;br /&gt;
==RoboTest==&lt;br /&gt;
Veranstaltungsort: Bei Frankfurt am Main&lt;br /&gt;
&lt;br /&gt;
Nächster Termin: voraussichtlich im Herbst 2009&lt;br /&gt;
&lt;br /&gt;
'''LINE SEARCH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Die Linie ist 2 bis 3cm breit. Es starten immer zwei Roboter gleichzeitig in einem Parallelslalom. Der Wettbewerb läuft in mehreren Runden nach dem KO-System. &lt;br /&gt;
&lt;br /&gt;
'''BLOCKED LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke ohne Abzweigungen. Auf der Strecke stehen Hindernisse, die umfahren werden müssen. &lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2 bis 5cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, innerhalb von drei Minuten möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegnerische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''MICRO LINE'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen für sehr kleine Roboter. Die maximale Größe liegt bei 8x8x8cm und 200g. Je kleiner und leichter der Roboter ist, desto mehr Bonuspunkte gibt es.  &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Es geht darum, eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude zu finden und zu löschen. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinander an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''JUST WALK'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 1m zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREE ROBOTS'''&amp;lt;br&amp;gt;&lt;br /&gt;
Hier können eigene Roboter dem Publikum vorgestellt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://WWW.ROBOTEST.DE/ RoboTest]&lt;br /&gt;
&lt;br /&gt;
==SPURT==&lt;br /&gt;
Der Wettbewerb SPURT (die Abkürzung steht für &amp;quot;Schüler-Projekte um Roboter-Technik&amp;quot;) wird jährlich von der Universität Rostock veranstaltet. SPURT richtet sich an technikinteressierte Schüler. Die zu lösende Aufgabe ist eine Linienverfolgung. Wer am schnellsten die herzförmige Linie abfährt, hat gewonnen.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://spurt.uni-rostock.de/ Wettbewerb SPURT]&lt;br /&gt;
&lt;br /&gt;
==ELROB==&lt;br /&gt;
Die deutsche Bundeswehr möchte Firma und Privatpersonen einladen, am European Land-Robot Trial 2006 (ELROB 2006) teilzunehmen.  Die ELROB wird veranstaltet, um einen Überblick über den europäischen State-of-the-art auf dem Gebiet von UGVs (unmanned ground vehicles) mit Fokus auf kurzfristig realisierbare Robotersystemen zu liefern.  Hinsichtlich der vorhandenen Fähigkeiten versuchen die Organisatoren, technische Lösungen zu fördern, die den Betrieb unbemannter Fahrzeuge (UGV) verbessern.  Repräsentanten aus Militär, Grenzschutz, Spezialkräften, Polizei, Feuerwehr, und Zivilschutzagenturen aus vielen europäischen Ländern werden anwesend sein.  Die ELROB wird von einer Ausstellung begleitet, welche eine breite Vielzahl an Robotikaspekten umfasst.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* [http://www.elrob2006.org/ Wettbewerb ELROB 2006]&lt;br /&gt;
&lt;br /&gt;
==GSF Robot Contest==&lt;br /&gt;
Ein neuer Wettbewerb für Hobbyrobotiker. Er findet am 19.5.07 erstmals statt. Austragunsordt ist Fröndenberg (Raum Dortmund/Unna).&lt;br /&gt;
Die Aufgaben sind teilweise angelehnt an die der RobotLiga.&lt;br /&gt;
&lt;br /&gt;
'''LABYRINTH'''&amp;lt;br&amp;gt;&lt;br /&gt;
Linienfolgen auf einer Strecke mit Abzweigungen und Kreuzungen. Die Linie ist 2cm breit.&lt;br /&gt;
&lt;br /&gt;
'''ROBOT COLLECT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Auf einem Spielfeld von 3x3m sind 30 Objekte in der Größe von Teelichtern verteilt. Zwei Roboter treten gegeneinander an und versuchen, möglichst viele der Objekte in ihre eigene Heimatecke des Spielfeldes zu bringen. &lt;br /&gt;
&lt;br /&gt;
''' ROBOT VOLLEY'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das Spielfeld ist 2x4m groß und wird durch eine Wand (als &amp;quot;Netz&amp;quot;) in zwei Hälfte geteilt, in denen je ein Roboter positioniert wird. In jeder Hälfte befinden sich am Anfang zehn Bälle. Die Roboter müssen nun innerhalb von fünf Minuten versuchen, möglichst viele der Bälle einzusammeln und in die gegenrische Hälfte zu befördern. &lt;br /&gt;
&lt;br /&gt;
'''FIRE FIGHTING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Naqch einem akustischen &amp;quot;Feueralarm&amp;quot; muss eine brennende Kerze in einem durch mehrere Wände angedeuteten Gebäude gefunden und gelöscht werden. &lt;br /&gt;
&lt;br /&gt;
'''MINI SUMO'''&amp;lt;br&amp;gt;&lt;br /&gt;
Zwei Roboter treten gegeneinader an und versuchen, sich aus dem Ring zu schieben.&lt;br /&gt;
&lt;br /&gt;
'''WALKING'''&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Disziplin nur für Laufroboter. Der Roboter muss schnellstmöglich eine Strecke von 100cm zurücklegen, wenden, und die Strecke zurück laufen. &lt;br /&gt;
&lt;br /&gt;
'''FREESTYLE'''&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Disziplin hat jeder Teilnehmer die Möglichkeit seinen Roboter vorzustellen und zu zeigen was dieser kann.&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www.gsf-robot-contest.de/&lt;br /&gt;
&lt;br /&gt;
==ROBOCOM==&lt;br /&gt;
Bei diesem Wettbewerb soll eine vorgegebene Aufgabe mit LEGO MINDSTORMS NXT Robotern autonom, d.h. ohne Eingriffe von außen bewältigt werden. Mit diesem Wettbewerb möchte die Fachhochschule Gelsenkirchen in den Schulen den Einsatz moderner Techniken fördern und Schülerinnen und Schüler für ein naturwissenschaftliches Studium interessieren.&amp;lt;br&amp;gt;&lt;br /&gt;
Am 15.06.2007 fand der Schülerwettbewerb ROBOCOM2007 zum erstem Mal statt. Am 26.06.2009 veranstaltet die Fachhochschule Gelsenkirchen die ROBOCOM2009.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Weblinks:'''&lt;br /&gt;
* http://www2.fh-gelsenkirchen.de/FH-Sites/FB1/index.php?id=791&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Praxis]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14101</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14101"/>
				<updated>2008-10-27T19:51:35Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header srf08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen. Kann auch Null sein.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 5&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren&lt;br /&gt;
void start_SRF08_automessung(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
//Ende von srf08.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode srf08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
//Variablen für die state machine&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//regelmäßig aufrufen!&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0; //Zähler für die Pause&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Interne Funktionen. Nicht im hauptprogramm aufrufen!&lt;br /&gt;
&lt;br /&gt;
//messung auslösen&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Prüfen, ob Sensor bereit zum Auslesen ist&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Daten vom Sensor lesen&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//ende von srf08.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als srf08.h und srf08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Beispiel für den Aufruf der SRF08-Routinen&lt;br /&gt;
 Die Timer-konfiguration ist angepasst für einen Mega16/32.&lt;br /&gt;
 Ansonsten müsste der Code auf allen AVRs mit I2C-Schnittstelle funktionieren.&lt;br /&gt;
 Getestet bis jetzt nur auf einem mega16.&lt;br /&gt;
 uwegw, 23.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;quot;srf08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    //timer1 für 10ms-Interrupt starten&lt;br /&gt;
	TIMSK |=(1&amp;lt;&amp;lt;OCIE1A); //ctc interrupt&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;CS12) | (1&amp;lt;&amp;lt;CS10); //Prescaler 1024&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;WGM12);	//Clear Timer on Compare Match Modus&lt;br /&gt;
	OCR1A = 0x009C; 	//Compare auf 10ms bei 8MHz setzen&lt;br /&gt;
&lt;br /&gt;
    sei();&lt;br /&gt;
    start_SRF08_automessung(); //Messung beginnen&lt;br /&gt;
&lt;br /&gt;
    uint16_t messwert; &lt;br /&gt;
    while(1)&lt;br /&gt;
    {&lt;br /&gt;
    messwert=get_SRF08_distance();&lt;br /&gt;
&lt;br /&gt;
   /*&lt;br /&gt;
    Messwert verarbeiten...&lt;br /&gt;
   */	&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect) //wird alle 10ms aufgerufen&lt;br /&gt;
{&lt;br /&gt;
	SRF08_task(); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Quellcode C]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14018</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14018"/>
				<updated>2008-09-23T12:20:25Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Beispiel für den Aufruf im Hauptprogramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header srf08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen. Kann auch Null sein.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 5&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren&lt;br /&gt;
void start_SRF08_automessung(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
//Ende von srf08.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode srf08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
//Variablen für die state machine&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//regelmäßig aufrufen!&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0; //Zähler für die Pause&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Interne Funktionen. Nicht im hauptprogramm aufrufen!&lt;br /&gt;
&lt;br /&gt;
//messung auslösen&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Prüfen, ob Sensor bereit zum Auslesen ist&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Daten vom Sensor lesen&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//ende von srf08.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als srf08.h und srf08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Beispiel für den Aufruf der SRF08-Routinen&lt;br /&gt;
 Die Timer-konfiguration ist angepasst für einen Mega16/32.&lt;br /&gt;
 Ansonsten müsste der Code auf allen AVRs mit I2C-Schnittstelle funktionieren.&lt;br /&gt;
 Getestet bis jetzt nur auf einem mega16.&lt;br /&gt;
 uwegw, 23.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;quot;srf08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    //timer1 für 10ms-Interrupt starten&lt;br /&gt;
	TIMSK |=(1&amp;lt;&amp;lt;OCIE1A); //ctc interrupt&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;CS12) | (1&amp;lt;&amp;lt;CS10); //Prescaler 1024&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;WGM12);	//Clear Timer on Compare Match Modus&lt;br /&gt;
	OCR1A = 0x009C; 	//Compare auf 10ms bei 8MHz setzen&lt;br /&gt;
&lt;br /&gt;
    sei();&lt;br /&gt;
    start_SRF08_automessung(); //Messung beginnen&lt;br /&gt;
&lt;br /&gt;
    uint16_t messwert; &lt;br /&gt;
    while(1)&lt;br /&gt;
    {&lt;br /&gt;
    messwert=get_SRF08_distance();&lt;br /&gt;
&lt;br /&gt;
   /*&lt;br /&gt;
    Messwert verarbeiten...&lt;br /&gt;
   */	&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect) //wird alle 10ms aufgerufen&lt;br /&gt;
{&lt;br /&gt;
	SRF08_task(); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Quellcode C]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14017</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14017"/>
				<updated>2008-09-23T12:19:28Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Header SRF08.h */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header srf08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen. Kann auch Null sein.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 5&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren&lt;br /&gt;
void start_SRF08_automessung(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
//Ende von srf08.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode srf08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
//Variablen für die state machine&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//regelmäßig aufrufen!&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0; //Zähler für die Pause&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Interne Funktionen. Nicht im hauptprogramm aufrufen!&lt;br /&gt;
&lt;br /&gt;
//messung auslösen&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Prüfen, ob Sensor bereit zum Auslesen ist&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Daten vom Sensor lesen&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//ende von srf08.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als SRF08.h und SRF08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Quellcode C]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14016</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14016"/>
				<updated>2008-09-23T12:17:46Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Quellcode SRF08.c */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header SRF08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen. Kann auch Null sein.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 5&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren&lt;br /&gt;
void start_SRF08_automessung(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
//Ende von srf08.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode srf08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
//Variablen für die state machine&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//regelmäßig aufrufen!&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0; //Zähler für die Pause&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Interne Funktionen. Nicht im hauptprogramm aufrufen!&lt;br /&gt;
&lt;br /&gt;
//messung auslösen&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Prüfen, ob Sensor bereit zum Auslesen ist&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Daten vom Sensor lesen&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//ende von srf08.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als SRF08.h und SRF08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Quellcode C]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14015</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14015"/>
				<updated>2008-09-23T12:17:20Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Header SRF08.h */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header SRF08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 23.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen. Kann auch Null sein.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 5&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren&lt;br /&gt;
void start_SRF08_automessung(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
//Ende von srf08.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode SRF08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0;&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){	srf08_auto_aktiv=1;} else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als SRF08.h und SRF08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Quellcode C]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14014</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14014"/>
				<updated>2008-09-23T12:16:53Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Beispiel für den Aufruf im Hauptprogramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header SRF08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 10&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode SRF08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0;&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){	srf08_auto_aktiv=1;} else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als SRF08.h und SRF08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void start_SRF08_automessung(void)&lt;br /&gt;
{&lt;br /&gt;
	i2c_init();&lt;br /&gt;
	srf08_auto_aktiv=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){srf08_auto_aktiv=1; i2c_init(); } else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Quellcode C]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14013</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14013"/>
				<updated>2008-09-22T20:25:22Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header SRF08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 10&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode SRF08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0;&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){	srf08_auto_aktiv=1;} else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als SRF08.h und SRF08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Beispiel für den Aufruf der SRF08-Routinen&lt;br /&gt;
 Die Timer-konfiguration ist angepasst für einen Mega16/32.&lt;br /&gt;
 Ansonsten müsste der Code auf allen AVRs mit I2C-Schnittstelle funktionieren.&lt;br /&gt;
 Getestet bis jetzt nur auf einem mega16.&lt;br /&gt;
 uwegw, 22.9.08&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    //timer1 für 10ms-Interrupt starten&lt;br /&gt;
	TIMSK |=(1&amp;lt;&amp;lt;OCIE1A); //ctc interrupt&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;CS12) | (1&amp;lt;&amp;lt;CS10); //Prescaler 1024&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;WGM12);	//Clear Timer on Compare Match Modus&lt;br /&gt;
	OCR1A = 0x009C; 	//Compare auf 10ms bei 8MHz setzen&lt;br /&gt;
&lt;br /&gt;
    sei();&lt;br /&gt;
    i2c_init(); &lt;br /&gt;
    set_SRF08_automessung(1); //Messung beginnen&lt;br /&gt;
&lt;br /&gt;
    uint16_t messwert;&lt;br /&gt;
    while(1)&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
    messwert=get_SRF08_distance();&lt;br /&gt;
&lt;br /&gt;
   /*&lt;br /&gt;
    Messwert verarbeiten...&lt;br /&gt;
   */&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect) //wird alle 10ms aufgerufen&lt;br /&gt;
{&lt;br /&gt;
	SRF08_task(); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Quellcode C]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14012</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14012"/>
				<updated>2008-09-22T20:21:53Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header SRF08.h ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 10&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode SRF08.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0;&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){	srf08_auto_aktiv=1;} else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
Die beiden Codeblöcke als SRF08.h und SRF08.c abspeichern, und i2cmaster.h sowie twimaster.c ins Programmverzeichnis kopieren.&lt;br /&gt;
&lt;br /&gt;
Im Makefile müssen die Quelldateien SRF08.c und twimaster.c hinzugefügt werden. Dazu unter der Überschrift&lt;br /&gt;
 # List C source files here. (C dependencies are automatically generated.)&lt;br /&gt;
die Zeilen&lt;br /&gt;
 SRC += srf08.c&lt;br /&gt;
 SRC += twimaster.c&lt;br /&gt;
einfügen.&lt;br /&gt;
&lt;br /&gt;
Anwendungsbeispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Beispiel für den Aufruf der SRF08-Routinen&lt;br /&gt;
 Die Timer-konfiguration ist angepasst für einen Mega16/32.&lt;br /&gt;
 Ansonsten müsste der Code auf allen AVRs mit I2C-Schnittstelle funktionieren.&lt;br /&gt;
 Getestet bis jetzt nur auf einem mega16.&lt;br /&gt;
 uwegw, 22.9.08&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    //timer1 für 10ms-Interrupt starten&lt;br /&gt;
	TIMSK |=(1&amp;lt;&amp;lt;OCIE1A); //ctc interrupt&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;CS12) | (1&amp;lt;&amp;lt;CS10); //Prescaler 1024&lt;br /&gt;
	TCCR1B |=(1&amp;lt;&amp;lt;WGM12);	//Clear Timer on Compare Match Modus&lt;br /&gt;
	OCR1A = 0x009C; 	//Compare auf 10ms bei 8MHz setzen&lt;br /&gt;
&lt;br /&gt;
    sei();&lt;br /&gt;
    i2c_init(); &lt;br /&gt;
    set_SRF08_automessung(1); //Messung beginnen&lt;br /&gt;
&lt;br /&gt;
    uint16_t messwert;&lt;br /&gt;
    while(1)&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
    messwert=get_SRF08_distance();&lt;br /&gt;
&lt;br /&gt;
   /*&lt;br /&gt;
    Messwert verarbeiten...&lt;br /&gt;
   */&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect) //wird alle 10ms aufgerufen&lt;br /&gt;
{&lt;br /&gt;
	SRF08_task(); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14010</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14010"/>
				<updated>2008-09-22T19:55:04Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [[Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm]] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde in diesem Artikel ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss die Funktion SRF08_task()regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Messung wird durch eine state machine gesteuert, die von SRF08_task() periodisch aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Zu Beginn ist die state machine im state SRF08_WARTEN_AUF_FREIGABE. Nur wenn die Messung aktiviert wurde (per set_SRF08_automessung(1);), wird auf SRF08_MESSUNG_STARTEN gewechselt. Hier wird das Kommando zum Start der Messung gesendet.&lt;br /&gt;
&lt;br /&gt;
Der Sensor lässt sich abfragen, ob er fertig mit der Messung ist und ausgelesen werden kann. Diese Abfrage geschieht in SRF08_MESSEN.&lt;br /&gt;
&lt;br /&gt;
Wenn die Messung beendet ist, wird in SRF08_AUSLESEN der Messwert einlesen und gespeichert.&lt;br /&gt;
&lt;br /&gt;
Zwischen zwei Messungen kann optional eine kurze Pause eingelegt werden. Dies wird in SRF08_PAUSE erledigt. Danach wird in SRF08_NEUSTART geprüft, ob eine neue Messung gestartet werden soll, und der Vorgang beginnt von vorne. &lt;br /&gt;
&lt;br /&gt;
===Header===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 10&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0;&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){	srf08_auto_aktiv=1;} else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für den Aufruf im Hauptprogramm ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14009</id>
		<title>SRF08 mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SRF08_mit_avr-gcc&amp;diff=14009"/>
				<updated>2008-09-22T19:42:09Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel beschreibt die Ansteuerung des Ultraschallsensors [[Sensorarten#SRF08|SRF08]] mit der Programmiersprache C (avr-gcc). &lt;br /&gt;
Für die I2C-Kommunikation wird die I2C-Master-lib von Peter Fleury verwendet, die unter [http://homepage.hispeed.ch/peterfleury/avr-software.html] zu finden ist. &lt;br /&gt;
&lt;br /&gt;
Der SRF08 hat gegenüber dem SRF05 den Vorteil, dass man die Entfernung direkt als digitalen Wert auslesen kann, und nicht die Länge eines Pulses messen muss. Daher kann man die Messung starten, und den Controller erst einmal andere Aufgaben erledigen lassen, bevor man den Messwert ausliest. Der Messvorgang dauert bis zu etwa 70ms, und in dieser Zeit kann der Controller sich anderen Aufgaben widmen. Im [Sensorarten#SRF08_Programmbeispiel|Bascom-Beispielprogramm] wird von dieser Möglichkeit nicht Gebrauch gemacht. Dies vereinfacht das Programm zwar enorm, verschwendet aber reichlich Rechenzeit. Daher wurde für das Programm ein anderer Ansatz gewählt. Er ist zwar deutlich komplexer, man kann aber die Programmdateien einfach übernehmen und in sein eigenes Projekt einbinden, ohne sich mit den Details der Umsetzung beschäftigen zu müssen.&lt;br /&gt;
&lt;br /&gt;
===Prinzip des Programms===&lt;br /&gt;
Es wird fortlaufend gemessen, der Messwert wird ständig aktualisiert. Dazu muss eine Funktion regelmäßig aufgerufen werden, die den Ablauf steuert. Dies sollte in einem Timer-Interrupt passieren. Es muss sichergestellt werden, dass währenddessen von keiner anderen Funktion auf den I2C-Bus zugegriffen wird!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Header===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#ifndef SRF08_H&lt;br /&gt;
#define SRF08_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;i2cmaster.h&amp;quot; //I2C-master-lib von P. Fleury verwenden&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//I2C-Busadresse&lt;br /&gt;
#define SRF08_adress 0xE0&lt;br /&gt;
&lt;br /&gt;
//Pause zwischen zwei Messungen.&lt;br /&gt;
// Task-Aufrufintervall * SRF08_DELAY = Pausenzeit&lt;br /&gt;
#define SRF08_DELAY 10&lt;br /&gt;
&lt;br /&gt;
//Task für die State Machine, alle 10ms aufrufen!&lt;br /&gt;
extern void SRF08_task(void);&lt;br /&gt;
&lt;br /&gt;
//Automatische Messung aktivieren/deaktivieren&lt;br /&gt;
// on: 1 oder 0, Automessung an/aus&lt;br /&gt;
extern void set_SRF08_automessung(uint8_t on);&lt;br /&gt;
&lt;br /&gt;
//Verstärkung setzen&lt;br /&gt;
extern void set_SRF08_gain(uint8_t gainvalue);&lt;br /&gt;
&lt;br /&gt;
//max. Reichweite festlegen&lt;br /&gt;
extern void set_SRF08_range(uint8_t rangevalue);&lt;br /&gt;
&lt;br /&gt;
//gemessene Entfernung in cm zurückgeben&lt;br /&gt;
extern uint16_t get_SRF08_distance(void);&lt;br /&gt;
&lt;br /&gt;
//gemessene Lichtstärke (0..255) zurückgeben&lt;br /&gt;
extern uint8_t get_SRF08_light(void);&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quellcode ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Auslesen des SRF08 Ultraschallsensors über I2C&lt;br /&gt;
Der Sensor wird fortlaufend ausgelesen und neu gestartet. Dazu muss SRF08_task() regelmäßig aufgerufen werden.&lt;br /&gt;
Mit den Funktionen get_SRF08_distance() und get_SRF08_light() kann man den letzten Messwert abrufen&lt;br /&gt;
uwegw, 22.9.08&lt;br /&gt;
Die Messung ist als state machine realisiert.&lt;br /&gt;
SRF08_WARTEN_AUF_FREIGABE: abwarten, bis Automessung aktiviert wurde&lt;br /&gt;
SRF08_MESSUNG_STARTEN: messvorgang starten&lt;br /&gt;
SRF08_MESSEN: Messung läuft, warten auf Ende&lt;br /&gt;
SRF08_AUSLESEN: Messwert einlesen&lt;br /&gt;
SRF08_PAUSE: Pause zwischen zwei Messungen&lt;br /&gt;
SRF08_NEUSTART: prüfen, ob Messung erneut gestartet werden soll.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;SRF08.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
volatile unsigned char srf08_auto_aktiv=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
volatile uint16_t SRF08_messwert=0;&lt;br /&gt;
volatile uint8_t SRF08_light=0;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t SRF08_gainvalue=5;&lt;br /&gt;
volatile uint8_t SRF08_rangevalue= 140; //6m default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Deklarationen für interne Funktione, nicht im Header enthalten&lt;br /&gt;
void SRF08_messung_starten(void);&lt;br /&gt;
uint8_t srf08_ready(void);&lt;br /&gt;
void srf08_auslesen(void);&lt;br /&gt;
&lt;br /&gt;
enum SRF08_STATES {SRF08_WARTEN_AUF_FREIGABE,SRF08_MESSUNG_STARTEN,SRF08_MESSEN,SRF08_AUSLESEN,SRF08_PAUSE,SRF08_NEUSTART};&lt;br /&gt;
uint8_t srf08_state=0;&lt;br /&gt;
&lt;br /&gt;
void SRF08_task(void)&lt;br /&gt;
{&lt;br /&gt;
static volatile uint8_t srf_delaycnt=0;&lt;br /&gt;
&lt;br /&gt;
	switch(srf08_state)&lt;br /&gt;
	{&lt;br /&gt;
	&lt;br /&gt;
		case SRF08_WARTEN_AUF_FREIGABE: //Messung war abgeschaltet, warten bis wieder aktiviert SRF08_WARTEN_AUF_FREIGABE&lt;br /&gt;
		if(srf08_auto_aktiv)&lt;br /&gt;
		{&lt;br /&gt;
			srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		//messung starten SRF08_MESSUNG_STARTEN&lt;br /&gt;
		case SRF08_MESSUNG_STARTEN: &lt;br /&gt;
		SRF08_messung_starten();&lt;br /&gt;
		srf08_state=SRF08_MESSEN;&lt;br /&gt;
		break;&lt;br /&gt;
		&lt;br /&gt;
		//messung läuft noch, warten bis Ende SRF08_MESSEN&lt;br /&gt;
		case 2: &lt;br /&gt;
		if(srf08_ready())&lt;br /&gt;
			{	&lt;br /&gt;
			srf08_state=SRF08_AUSLESEN;&lt;br /&gt;
			}&lt;br /&gt;
		break;&lt;br /&gt;
	&lt;br /&gt;
		//messung fertig, Werte auslesen SRF08_AUSLESEN&lt;br /&gt;
		case 3: &lt;br /&gt;
			srf08_auslesen();&lt;br /&gt;
			srf08_state=SRF08_PAUSE;&lt;br /&gt;
			srf_delaycnt=SRF08_DELAY;&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
		//messung fertig, evtl Pause machen SRF08_PAUSE&lt;br /&gt;
		case SRF08_PAUSE:&lt;br /&gt;
			if(srf_delaycnt)&lt;br /&gt;
				{&lt;br /&gt;
				srf_delaycnt--;&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
				srf08_state=SRF08_NEUSTART;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
		break;		&lt;br /&gt;
		&lt;br /&gt;
		//wenn weiterhin gemessen werden soll, im nächsten zyklus nächste Messung starten SRF08_NEUSTART&lt;br /&gt;
		case SRF08_NEUSTART: &lt;br /&gt;
			if(srf08_auto_aktiv)&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_MESSUNG_STARTEN; //im nächsten Zyklus neue Messung beginnen&lt;br /&gt;
				}&lt;br /&gt;
			else&lt;br /&gt;
				{&lt;br /&gt;
					srf08_state=SRF08_WARTEN_AUF_FREIGABE; //Automessung stoppen&lt;br /&gt;
				}&lt;br /&gt;
		break;	&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		default:&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SRF08_messung_starten(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Gainregister&lt;br /&gt;
		i2c_write(SRF08_gainvalue);//Gain setzen&lt;br /&gt;
		i2c_write(SRF08_rangevalue);&lt;br /&gt;
	&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x00);//Befehlsregister wählen		&lt;br /&gt;
		i2c_write(0x51);//Messung starten, Ergebnis in cm&lt;br /&gt;
		&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint16_t get_SRF08_distance(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_messwert;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_SRF08_light(void)&lt;br /&gt;
{&lt;br /&gt;
return SRF08_light;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_automessung(uint8_t on)&lt;br /&gt;
{&lt;br /&gt;
	if(on){	srf08_auto_aktiv=1;} else {srf08_auto_aktiv=0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_gain(uint8_t gainvalue)&lt;br /&gt;
{&lt;br /&gt;
	SRF08_gainvalue=gainvalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void set_SRF08_range(uint8_t rangevalue)&lt;br /&gt;
{&lt;br /&gt;
		SRF08_rangevalue=rangevalue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t srf08_ready(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
if(!(i2c_start(SRF08_adress+I2C_WRITE)))&lt;br /&gt;
	{	i2c_stop();&lt;br /&gt;
		return 1;&lt;br /&gt;
	}	&lt;br /&gt;
i2c_stop();&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void srf08_auslesen(void)&lt;br /&gt;
{&lt;br /&gt;
	if(srf08_ready())&lt;br /&gt;
	{&lt;br /&gt;
		i2c_start(SRF08_adress+I2C_WRITE);&lt;br /&gt;
		i2c_write(0x01);//Ergebnisregister Lichtsensor wählen&lt;br /&gt;
		i2c_rep_start(SRF08_adress+I2C_READ);&lt;br /&gt;
				&lt;br /&gt;
		SRF08_light= i2c_readAck();&lt;br /&gt;
		SRF08_messwert = ((i2c_readAck())&amp;lt;&amp;lt;8); //highbyte&lt;br /&gt;
		SRF08_messwert += (i2c_readNak()); //lowbyte&lt;br /&gt;
		i2c_stop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Sensorarten&amp;diff=14008</id>
		<title>Sensorarten</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Sensorarten&amp;diff=14008"/>
				<updated>2008-09-22T19:10:27Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* SRF08 Programmbeispiel */  Link zu SRF08 Programm in C hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Welche Sensorarten gibt es==&lt;br /&gt;
Damit sich ein Roboter in seiner Umgebung bewegen kann, ohne an Hindernisse anzustoßen, und damit er ein Ziel finden und ansteuern kann, muß er irgendwie seine Umwelt &amp;quot;wahrnehmen&amp;quot;. &lt;br /&gt;
Hauptanwendung für diese Informationen aus der Umwelt ist die [[Navigation]].&lt;br /&gt;
Auf dieser Seite werden die wichtigsten Sensorarten und damit es praktischer wird auch zugleich die populärsten Robotik- und Modellbau-Sensortypen vorgestellt. Auch die Pinbelegung und Anschlussmöglichkeiten dieser Sensoren werden kurz erläutert.&lt;br /&gt;
&lt;br /&gt;
==Bumpers==&lt;br /&gt;
Als Bumpers bezeichnet man eine Art Stoßstange, die einen Mikro-Switch auslöst. &lt;br /&gt;
&lt;br /&gt;
[[Bild:microschalter.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Die Auswertung erfolgt am besten digital an einem Pin mit Pull-up Widerstand. Man kann den Eingang pollen (abfragen), aber auch einen Interrupt auslösen lassen. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Whiskers (Fühler)==&lt;br /&gt;
Das sind flexible Kunststoff-Streifen von ca. 10 cm Länge, eigentlich für Datenhandschuhe vorgesehen. Aber man kann sie auch als Fühler einsetzen, und daher auch für die Kollisions-Sensorik verwenden. Beim Verbiegen steigt der Widerstand an.  &lt;br /&gt;
&lt;br /&gt;
[[Bild:flexs_200.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Um zu messen, wird mit einem zweiten Widerstand ein Spannungsteiler aufgebaut, der dann mit einem Analog-Eingang einen Grad der Verbiegung erkennen läßt. Sie werden häufig auch Flexsensoren genannt. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Incremental-Geber==&lt;br /&gt;
Dienen zur Erfassung von Drehzahl bzw. der Messung von Wegstrecken&lt;br /&gt;
&lt;br /&gt;
===austriamicrosystems AS5040===&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Bild:AMS-general_200x200.jpg|right]]&lt;br /&gt;
[[Bild:AMS-chip_109x104.jpg|left]]&lt;br /&gt;
&lt;br /&gt;
Der AS5040 kann absolute Winkelpositionen an einer Achse messen. Die Messung wird indirekt über ein Magnetfeld mittels Hallsensoren durchgeführt. Aufgrund der Anordnung der Hallsensoren und der Integration der Sensoren direkt in Silizium wird eine sehr hohe Genauigkeit bei der Messung erreicht. Das Messprinzip kompensiert ausserdem Störgrössen, wie externes Magnetfeld, Alterungseinflüsse, Temperaturschwankungen und mechanische Toleranzen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Die komplette Auswertung der Sensorsignale geschieht auf dem Chip. &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:AMS-block_700x242.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:AMS-pcb_200x152.jpg|right]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Durch die hohe Integration reduziert sich die zusätzliche Beschaltung des Chips auf wenige Bauteile, beispielsweise ein paar Filterkondensatoren. &lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Die Winkelencoderfamilie von austriamicrosystems besitzt vielfältige Schnittstellen um den Winkelwert zu übertragen&lt;br /&gt;
&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |Seriell SSI&lt;br /&gt;
 |Standard Schnittstelle für Winkelencoder in der Industrie&lt;br /&gt;
 |-&lt;br /&gt;
 |PWM&lt;br /&gt;
 |erzeugt abhängig vom Winkel eine entsprechende Pulslänge, läßt sich sehr schön mit der Capturefunktion eines Controllers messen und braucht nur eine Leitung&lt;br /&gt;
 |-&lt;br /&gt;
 |I2C&lt;br /&gt;
 |direkte Schnittstelle zum Microcontroller&lt;br /&gt;
 |-&lt;br /&gt;
 |Analog&lt;br /&gt;
 |kompatible Schnittstelle um beispielsweise Potiapplikationen zu ersetzen&lt;br /&gt;
 |-&lt;br /&gt;
&lt;br /&gt;
 |Inkremental&lt;br /&gt;
 |klassische Schnittstelle um relative Bewegungen zu messen, keine Absolutmessung möglich&lt;br /&gt;
 |-&lt;br /&gt;
 |BLDC&lt;br /&gt;
 |erzeugt direkt die Kommutierung für einen bürstenlosen Motor. Durch die höhere Auflösung gegenüber einer 3-Hall-Schalterlösung kann der BLDC mit einem wesentlich höheren Drehmoment gestartet werden&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
[[Bild:AMS-magnet_354x421.jpg|left]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Bei der Auswahl des Magnetens ist darauf zu achten, dass sogenannte Selten-Erde Magnete verwendet werden. http://de.wikipedia.org/wiki/Seltene_Erden Diese erzeugen ein besonders starkes Magnetfeld, das im 1 Tesla Bereich liegt. Im Zentrum des Magnetfelds ist ein linearer Bereich, der für die Genauigkeit der Messung ausschlaggebend ist. Solange die Hallsensoren in diesem Bereich liegen, kann eine unkalibrierte Genauigkeit von +/- 0.5 Grad gewährleistet werden. Weiterhin ist zu beachten, dass der Magnet nicht direkt auf eine Eisenwelle montiert wird. Die Eisenwelle verursacht quasi einen magnetischen 'Kurzschluß' und entzieht damit den Hallsensoren das Magnetfeld. Idealerweise sollte eine NE-Welle verwendet werden, oder wenn nicht anders machbar muß eine Isolation aus NE-Material zwischen Eisenwelle und Magnet eingefügt werden.&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Ein einfacher erfolgreicher Test des Sensors ist hier beschrieben: http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=322373#322373&lt;br /&gt;
&lt;br /&gt;
===Drehgeber Sharp GP1A30 und GP1A38===&lt;br /&gt;
&lt;br /&gt;
[[Bild:gp1a30.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Beim Sharp GP1A30 und GP1A38 handelt es sich um Gabellichtschranken mit inkrementaler Drehgeberfunktion. Beide sind im Grunde von den Anschlüssen identisch, lediglich kann GP1A38 noch etwas höhere Drehzahlen messen. Im Gegensatz zu herkömmlichen Gabellichtschranken können mit dieser sowohl Drehzahl als auch Drehrichtung ermittelt werden. Notwendig sind dafür nur 2 digitale Ports. Verzichtet man auf die Auswertung der Drehrichtung, reicht nur ein Port.&lt;br /&gt;
Der Sensor hat den Vorteil das die Signale bereits TTL kompatibel sind und direkt an ein Controllerboard angeschlossen werden können. Ein Beispielprogramm zu [[RN-Control]] findet man hier&lt;br /&gt;
&lt;br /&gt;
* [[Beispiel Drehzahlmessung mit RN-Control]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:GP1A30.gif|center]]&lt;br /&gt;
&lt;br /&gt;
Die Auswertung inkrementaler Drehgeber ist recht einfach. Ein Ausgang liefert einen Impuls pro Markierung (Scheibe auf der Welle). Prüft man bei jedem Impuls (Flanke) noch gleichzeitig den aktuellen Pegel des zweiten Ausganges, so kann daraus die Drehrichtung abgeleitet werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Signalverlauf an den Sensorausgängen ist phasenversetzt:&lt;br /&gt;
&lt;br /&gt;
[[Bild:inkremental1.gif|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:drehgeber_an_rncontrol.gif|center|framed|Beispielschaltung wenn man lediglich die Drehzahl ohne Drehrichtung auswerten möchte. Als Widerstand hat sich 330 Ohm als gut erwiesen.]]&lt;br /&gt;
&lt;br /&gt;
==Optische Sensoren==&lt;br /&gt;
===Helligkeit=== &lt;br /&gt;
Die Hauptanwendung solcher Sensoren ist, den hellsten Fleck im Raum zu finden.&lt;br /&gt;
Dies ist auch Teil vieler Roboterwettbewerbe. (Robo Callenge (2002 sic!), 'Ein Platz an der Sonne')&lt;br /&gt;
&lt;br /&gt;
Solche Sensoren können einfache [[LDR]]s oder [[Photodioden]] bzw. [[Phototransistoren]] sein.&lt;br /&gt;
LDRs haben den Vorteil, dass sie relativ hoch aussteuern, der große Nachteil ist aber, dass diese Sensoren ziemlich Wärmeempfindlich und etwas träge sind.&lt;br /&gt;
Photodioden und Phototransistoren haben den Vorteil, dass sie sehr genau sind, aber nicht besonders hoch aussteuern. Diese sollte man evtl. über einen OpAmp verstärken.&lt;br /&gt;
&lt;br /&gt;
[[Bild:fotowiderstand.jpg|center|framed|Ein typischer Fotowiderstand]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:SFH300.jpg|center|framed|SFH300, ein typischer Phototransistor]]&lt;br /&gt;
&lt;br /&gt;
Alternativ kann auch ein digitaler Lichtsensor verwendet werden, den man direkt an den I2C- oder SM-Bus anschliessen kann. Man erspart sich Auswertung, Temperaturkompensation und Signalaufbereitung, allerdings ist der Anschluss meistens schwieriger, weil der Sensor in SMD-Bauform gebaut ist und 3,3 anstatt 5 Volt braucht.&lt;br /&gt;
[[Bild:Lichtsensor.jpg|center|framed|Ein digitaler Lichtsensor für den I2C-Bus (TSL2561 der Frima Taos)]]&lt;br /&gt;
&lt;br /&gt;
Die Suche nach dem hellsten Fleck im Raum ist wie ich finde ein gutes Einsteigerthema!&lt;br /&gt;
&lt;br /&gt;
===CNY70===&lt;br /&gt;
&lt;br /&gt;
Der CNY70 ist ein Foto-Reflex Optokoppler. In einem würfelförmigem Gehäuse befindet sich eine Infrarot LED als Sender und ein Infrarot Fototransistor als Empfänger. Damit kann auf kurze Entfernung (wenige Millimeter) das reflektierte Licht der IR-LED durch den IR-Fototransistor gemessen werden.  &lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[Bild:cny70.jpg|thumb|200px|CNY70]]&lt;br /&gt;
|[[Bild:cny70_pinout.jpg|framed|CNY70 Vishay Pinout]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Achtung:''' Es existiert auch noch ein CNY70 von Temic mit anderer Pinbelegung, dort ist der Fototransistor verdreht eingebaut.&lt;br /&gt;
&lt;br /&gt;
Der CNY70 eignet sich für eine Vielzahl von Sensoren. Z.B. als Liniensensor, Radencoder, Abgrunddetektor und Lichtschranke. Allerdings ist er empfindlich gegen Streulicht, da  das Licht der IR-LED nicht moduliert ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:cny70_schem1.gif|thumb|center|600px|CNY70 als Liniensensor]]&lt;br /&gt;
&lt;br /&gt;
Der Liniensensor benötigt 2 A/D Wandler Eingänge des Prozessors. Die CNY70 sollten so nah wie möglich in Bodennähe angebracht sein (1..3mm). Der P-Kanal FET BS250 dient als Schalter für die IR LEDs des CNY70. Damit spart man Strom, wenn der Liniensensor nicht benötigt wird. Allerdings wird dafür ein weiterer Prozessor Ausgang als Enable Signal benötigt. HIGH Pegel schaltet die Sensor LEDs aus, LOW Pegel ein.  Wird keine Enable Funktion gewünscht, läßt man den BS250 einfach weg und hängt die Vorwiderstände der Sensor LEDs direkt an VCC.&lt;br /&gt;
&lt;br /&gt;
[[Bild:cny70_schem2.gif|thumb|center|600px|CNY70 als Radencoder mit Schmitt-Trigger]]&lt;br /&gt;
&lt;br /&gt;
Die Radencoder benötigen zwei digitale Eingangsports des Prozessors. A/D Wandler sind nicht nötig, da die Schmitt-Trigger Gatter für saubere Logik Signale sorgen. Die CNY70 sollten so nah wie möglch an den Rädern sitzen (1..2mm). Die gewählten Widerstandswerte für R17/R19 bzw. R18/R20 sind optimiert für Radencoder die auf Transparentfolie gedruckt und auf Aluminium Räder aufgeklebt werden. Für Radencoder die auf Papier ausgedruckt werden, sind andere Widerstandswerte notwendig.&lt;br /&gt;
Der P-Kanal FET BS250 dient als Schalter für die IR LEDs des CNY70. Damit spart man Strom, wenn der Radencoder nicht benötigt wird. Allerdings wird dafür ein weiterer Prozessor Ausgang als Enable Signal benötigt. HIGH Pegel schaltet die Sensor LEDs aus, LOW Pegel ein. Wird keine Enable Funktion gewünscht, läßt man den BS250 einfach weg und hängt die Vorwiderstände der Sensor LEDs direkt an VCC.&lt;br /&gt;
&lt;br /&gt;
===Distanzsensor IS471F===&lt;br /&gt;
&lt;br /&gt;
IS471F - Hinderniserkennung mit Infrarot Distanzsensor&lt;br /&gt;
&lt;br /&gt;
Das hier vorgestellte IC IS471F erlaubt eine einfach und sogar recht preisgünstige Hinderniserkennung per Infrarot. Dazu muß im wesentlichen nur noch eine Infrarot-Diode an das IC angeschlossen werden. Das modulierte Licht wird von einem Gegenstand direkt auf das IC zurückgeworfen und somit das Hindernis erkannt. Tageslicht/Fremdlicht stört den IS471 überhaupt nicht, da das Licht mit einer bestimmten Frequenz moduliert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:is471.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der normale Schaltungsaufbau sieht also wie oben abgebildet aus! In der Praxis kann das dann in etwa so aussehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:is471beispiel.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das englische Datenblatt findet man im Roboternetz-Download-Bereich&lt;br /&gt;
&lt;br /&gt;
Die normale Reichweite ist in gewissen Grenzen abhängig von der Farbe des Hindernises. In der Regel reicht es jedoch durchaus einige cm so das langsame Roboter durchaus sehr gut damit zurecht kommen. Durch besonders helle Infrarot LED´s und durch zusätzlich LED-Fassungen kann man die Reichweite erhöhen. Wem das noch nicht reicht, der kann über einen zusätzlichen Transistor die Strahlungsleistung der LED noch weiter erhöhen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:is471verstaerkung.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
http://www.roboternetz.de/bilder/mehrereis471.gif&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sharp Infrarotsensoren===&lt;br /&gt;
&lt;br /&gt;
Sharp hat eine ganz interessante Serie von Bausteinen herausgebracht mit denen ein Roboter sogar recht genau Entfernungen messen kann. Das Messergebnis ist nahezu unabhängig von der Farbe und Helligkeit des gemessenen Objektes. Die Ansteuerung ist sehr einfach, der Sensorausgang kann zum Beispiel direkt an einen analogen Eingang eines Mikrocontrollers angeschlossen werden. Die Sensoren sind unter den Roboter-Bastlern weit verbreitet. &lt;br /&gt;
Bei vielen Händlern erhältlich kosten die Sensoren derzeit je nach Typ und Händlerspanne zwischen 13 bis 25 Euro.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sharpentfernungssensor.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Oft werden selbst in kleinen Roboter-Projekten mehrere dieser Sensoren genutzt da sie nur einen äußerst engen Erfassungsbereich haben. Sie eignen sich daher sehr gut zur Vermessung einer Umgebung, insbesondere dann wenn Sie drehbar auf einem Servo montiert werden. Als Kollisionsschutz sind sie wegen dem engen Winkel nur bedingt geeignet, zu diesem Zweck eignen sich zum Beispiel Ultraschallsensoren besser.&lt;br /&gt;
Das Funktionsprinzip der Sensoren ist einfach. Der Sensor besteht aus Sender und Empfänger. Der Sender sendet einen Infrarot-Strahl aus, der vom Hindernis reflektiert wird. Je nach Entfernung trifft der reflektierte Strahl an einer unterschiedlichen Stelle auf den Empfänger (ein sog. Position Sensitive Device, PSD). Der Empfänger setzt den Auftreffpunkt in einen analogen Spannungswert um. Eine schöne Skizze dazu:  &lt;br /&gt;
&lt;br /&gt;
[[Bild:sharpfunktion.jpg|center]]&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Wenn man diese Sensoren an Robotern einsetzt, will man meist Hindernisse mit senkrecht stehenden Kanten erkennen. Montiert man den Sensor jedoch in waagerechter Lage, können sich Fehlmessungen ergeben, wenn sich ein Objekt am Sensor vorbeibewegt (z.B. wenn sich der Roboter dreht). Es wird an der Kante kurzzeitig ein Entfernung gemessen, die geringer als die tatsächliche Entfernung zum Hindernis ist. (oder auch größer als die Entfernung zu einem zweiten Hindernis hinter dem ersten, je nach Bewegungsrichtung!) Man löst dieses Problem, indem man den Sensor in senkrechter Position montiert, also so, dass die beiden Linsen übereinander statt nebeneinander liegen. Dies wird auch in Datenblatt des Sensors empfohlen: der Sensor sollte immer senkrecht zur Bewegungsrichtung des Hindernisses montiert werden.&lt;br /&gt;
&lt;br /&gt;
Sehr deutlich erkennt man diese Messfehler, wenn man den Sensor als ein Art 3D-Scanner einsetzt: http://www.team-iwan.de/technik/sharp1.php&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{|{{Blaueschmaltabelle}}&lt;br /&gt;
|&lt;br /&gt;
Die Gehäuse dieser Sensoren sehen wie ganz gewöhnlicher Kunststoff aus. Sie bestehen jedoch aus leitfähigem Material! (Kaum zu glauben, aber einfach nachprüfbar: zwischen den beiden Befestigungslöchern misst man einen Widerstand von etwa 250 bis 300 Ohm). Außerdem ist das Gehäuse mit dem Masseanschluss verbunden. Dies ist normalerweise nicht weiter wichtig, da die Sensoren meist entweder isoliert (zb auf Kunststoffteilen) oder auf einem geerdeten/mit Masse verbundenen Metallchassis montiert werden. Wenn man aber die Sensoren abschalten will, um Strom zu sparen (die Sensoren verbrauchen etwa 30 bis 40mA), muss man bei nicht isolierter Montage unbedingt die Plusleitung schalten! Wenn man die Masse-Zuleitung unterbricht, ist der Sensor sonst trotzdem noch über das Gehäuse und das Chassis mit Masse verbunden, und wird nicht deaktiviert!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Einige der beliebtesten Bausteine sind:'''&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D12==== &lt;br /&gt;
Distanz 10 - 80 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt&lt;br /&gt;
Dies ist der am häufigsten eingesetzte Sharp Typ bei mobilen Robotern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:GP2D12anschluss.gif|center]]&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2YA21YK==== &lt;br /&gt;
Distanz 10 - 80 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D120====&lt;br /&gt;
Distanz 4 - 30 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2Y0A02YK====&lt;br /&gt;
Distanz 20 - 150 cm - Entfernung wird durch analoge Spannung am Ausgang übermittelt&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
http://www.shop.robotikhardware.de/shop/catalog/images/artikelbilder/sensoren/gp2y0a02yk_diagramm.gif&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D02====&lt;br /&gt;
Distanz 10 - 80 cm - Entfernung wird durch 8 Bit Digitalausgang übermittelt&lt;br /&gt;
&lt;br /&gt;
====Sharp GP2D150====&lt;br /&gt;
Distanz 3-30 cm - 1 Bit Schaltausgang  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Datenblätter zu den oberen Sensoren findet man im Download-Bereich des Roboternetz, siehe unter [[#Weblinks]].&lt;br /&gt;
 &lt;br /&gt;
Um die analogen Spannung der Sensoren in eine Entfernung umzurechnen, kann man sich mit Hilfe des Datenblattes oder einfacher Probemessungen Tabellen erstellen, welche dann vom Controller zur Umsetzung genutzt werden.&lt;br /&gt;
Bequemer ist allerdings eine Näherungsformel:&lt;br /&gt;
&lt;br /&gt;
====Formel zur Entfernungsberechnung==== &lt;br /&gt;
 D = A/(X-B) &lt;br /&gt;
&lt;br /&gt;
 D ist die Entfernung &lt;br /&gt;
 X ist der Ausgabewert des Sensors &lt;br /&gt;
 A ist die Steigung der Kurve A/X &lt;br /&gt;
 B ist der Offset der Kurve &lt;br /&gt;
&lt;br /&gt;
Die Konstanten A und B ermittelt man am besten über zwei Probemessungen: &lt;br /&gt;
&lt;br /&gt;
D und X sind die Entfernung und der Ausgabewert der ersten Messung (z.B. bei 20 cm) &lt;br /&gt;
D' und X' sind die Entfernung und der Ausgabewert der zweiten Messung (z.B. bei 60 cm) &lt;br /&gt;
&lt;br /&gt;
 A = ((X' - X) * D' * D) /(D - D' ) &lt;br /&gt;
 B = (D' * X' - D * X) /(D' - D) &lt;br /&gt;
&lt;br /&gt;
====GP2D12 Messkurve====&lt;br /&gt;
&lt;br /&gt;
[[Bild:gpd12kurve.gif|center]]&lt;br /&gt;
&lt;br /&gt;
====GPD120 Messkurve====&lt;br /&gt;
&lt;br /&gt;
[[Bild:gpd120kurve.gif|center]]&lt;br /&gt;
&lt;br /&gt;
==Ultraschall Sensoren== &lt;br /&gt;
===Ultraschallsensoren SRF04===&lt;br /&gt;
Die Firma '''Devantech''' hat eine Serie von sehr günstigen und kleinen Ultraschallsensoren entwickelt, die sich im Bereich &amp;quot;autonome Robotersysteme&amp;quot; durchgesetzt haben. Sie sind sehr verbreitet, da sie auch für &amp;quot;Hobby-Robotiker&amp;quot; erschwinglich sind und es sich nicht lohnen würde vergleichbare Module selber zu bauen, da diese meistens ungenauer und teurer wären.&lt;br /&gt;
&lt;br /&gt;
Bekannt wurde die Serie durch den '''SRF04'''. Mit seinen kleinen Abmessungen, der niedrigen Stromaufnahme und der hohen Genauigkeit ist er für kleine Messaufgaben im Entfernungsbereich von 3cm bis 3m gut geeignet. Der SRF04 kann einen 3cm dicken Besenstiel in 2m Entfernung erkennen und wird durch ein [[PWM]]-Signal ausgewertet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf_04a.jpg]] [[Bild:srf_04.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Ultraschallsensor SRF05===&lt;br /&gt;
Der Nachfolger des SRF04 ist der neue SRF05. Er besitzt noch eine etwas höhere Reichweite bis 4 Meter. Zudem besitzt er neben dem kompatibel Mode zu SRF04 noch eine Betriebsart bei der er über einen einzigen Port (Pin) gesteuert wird. Das heißt sowohl der Start der Messung und das Ergebnis wird über die gleiche Leitung übertragen. [[Ultraschall SRF05 an RN-MiniControl|Programmbeispiel in Bascom]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Srf05mode1.jpg|center]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf05mode2.gif|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf05mode2diagram.gif|center]]&lt;br /&gt;
&lt;br /&gt;
===SRF08===&lt;br /&gt;
Die Alternative zu SRF04 und SRF05 ist der beliebte  '''SRF08''' und dessen Nachfolger '''SRF10''', der nun über den [[I2C]]-Bus ausgewertet werden kann und über eine Reichweite von 3cm bis 6m verfügt. Er hat eine noch kleinere Stromaufnahme und zusätzlich befindet sich auf der Platinenfront ein Fotowiderstand(LDR) dessen Lichtmesswerte sich ebenfalls über den [[I2C]]-Bus auswerten lassen. Durch den SRF08 wird es möglich auch bis zu 16 Mehrfachechos, von weiter hinten gelegenen Gegenständen, auszuwerten, die bei dem SRF04 ignoriert wurden. Über den [[I2C]]-Bus kann man die Messwerte in cm, zoll und in der Laufzeit µs auslesen und spart sich somit die externe Auswertung der Laufzeit, wie bei dem SRF04. Weiterhin können insgesamt 16 SRF08-Module an einen [[I2C]]-Bus angeschlossen werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf08_a.jpg]]  [[Bild:srf08_b.jpg]]&lt;br /&gt;
&lt;br /&gt;
===SRF08 Programmbeispiel===&lt;br /&gt;
&lt;br /&gt;
[[SRF08 mit avr-gcc|SRF08 Programmbeispiel mit AVR-GCC]]&lt;br /&gt;
&lt;br /&gt;
SFR08 Programm Beispiel mit [[Bascom]]&lt;br /&gt;
Über die grundsätzliche Behandlung des [[I2C]]-Bus mit [[Bascom]] kann man [[I2C|hier]] nachlesen. &lt;br /&gt;
&lt;br /&gt;
 Const Sf08_adr_0 = &amp;amp;HE0             ' I2C Adresse&lt;br /&gt;
 Const Sf08_c_range = 100            ' Reichweite&lt;br /&gt;
 Const Sf08_c_gain = 1               ' Empfindlichkeit&lt;br /&gt;
&lt;br /&gt;
Die Adresse ist der Default-Wert für den Sensor, und kann eingestellt werden. &lt;br /&gt;
Range und Gain sind anzupassen, die angegeben Werte sind aber mal grundsätzlich verwendbar.&lt;br /&gt;
&lt;br /&gt;
'''Setup'''&lt;br /&gt;
Nach dem Reset sind einmal Range und Gain zu setzen.&lt;br /&gt;
&lt;br /&gt;
'''Setzen Range'''&lt;br /&gt;
&lt;br /&gt;
      I2cstart&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 2            ' register &amp;quot;range&amp;quot;&lt;br /&gt;
      I2cwbyte Sf08_c_range  &lt;br /&gt;
      I2cstop&lt;br /&gt;
 &lt;br /&gt;
'''Setzen Gain'''&lt;br /&gt;
&lt;br /&gt;
      I2cstart&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 1            ' register &amp;quot;gain&amp;quot;&lt;br /&gt;
      I2cwbyte Sf08_c_gain    &lt;br /&gt;
      I2cstop&lt;br /&gt;
&lt;br /&gt;
'''Abfrage Trigger'''&lt;br /&gt;
&lt;br /&gt;
Die Abfrage soll laut Beschreibung in zwei Schritten erfolgen, zwischen denen ca 70 mS gewartet werden soll. Diese Zeit braucht das Gerät zum Messen. &lt;br /&gt;
&lt;br /&gt;
'''Trigger'''  &lt;br /&gt;
      I2cstart&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 0            ' register &amp;quot;Trigger&amp;quot;&lt;br /&gt;
      I2cwbyte 81           ' Meßwert in Zentimetern&lt;br /&gt;
&lt;br /&gt;
      Waitms 70 &lt;br /&gt;
&lt;br /&gt;
'''Ergebnis abholen'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 DIM Lsb as Byte&lt;br /&gt;
 DIM Msb as Byte&lt;br /&gt;
 DIM IVal as word&lt;br /&gt;
&lt;br /&gt;
      I2cstart              ' Repeated Start&lt;br /&gt;
      I2cwbyte Sf08_adr_0   ' Device I2C Adresse&lt;br /&gt;
      I2cwbyte 2            ' Meßwert US&lt;br /&gt;
&lt;br /&gt;
      I2cstart                 ' repeated Start&lt;br /&gt;
      I2cwbyte Sf08_adr_0 + 1  ' Device I2C Adresse READ!&lt;br /&gt;
      I2crbyte Msb , Ack      ' Bit 8-15&lt;br /&gt;
      I2crbyte Lsb , Nack     ' Bit 0-7&lt;br /&gt;
      I2cstop&lt;br /&gt;
&lt;br /&gt;
      Ival = Makeint(lsb , Msb) ' umwandeln in Word (16 Bit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SRF10 Ultraschallsensor ===&lt;br /&gt;
SRF10 ist quasi der Nachfolger von SRF08. Er bietet die gleiche Leistung und ist sogar gegenüber Spannungsschwankungen noch etwas unempfindlicher als der Vorgänger. Der größte Vorteil besteht jedoch darin das er ca. 1/3 kleiner als sein Vorgänger ist.   &lt;br /&gt;
&lt;br /&gt;
[[Bild:srf10foto1.jpg]] [[Bild:srf10foto2.gif]]&lt;br /&gt;
&lt;br /&gt;
Die technischen Daten sind ähnlich:&lt;br /&gt;
* Betriebsspannung: 5V &lt;br /&gt;
* Stromaufnahme: ca. 3mA Standby, ca. 15mA während des Messens Frequenz: 40KHz &lt;br /&gt;
* Maximale Reichweite: 6 m &lt;br /&gt;
* Minimale Reichweite: 4 cm &lt;br /&gt;
* Messwerterfassung: intern, kein externer Controller zur Zeitmessung notwendig &lt;br /&gt;
* Interface: Standard – I2C (passend zu zahlreichen Controllerboards, z.B. RN-Control) &lt;br /&gt;
* Ausgabeformat: µs, cm oder Zoll &lt;br /&gt;
* Feature: Analogverstärkung 40 - 700 (einstellbar, 16 Stufen) &lt;br /&gt;
* Abmessungen: 32mm x 15mm x 10mm &lt;br /&gt;
* Hersteller: Devantech Ltd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[Ultraschall_SRF10_an_RN-Control|Programmbeispiel in Bascom]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:srf10ausbreitung.gif|center]]&lt;br /&gt;
&lt;br /&gt;
===SRF02 Ultraschallsensor===&lt;br /&gt;
Der erste Sensor aus der SRF-Reihe der mit nur einem Ultraschallwandler auskommt. Dennoch können sich die Leistungen zeigen. Vorallem die Tatsache das sowohl RS232 und I2C-Bus Schnittstelle vorhanden ist dürfte viele Bastler erfreuen.&lt;br /&gt;
&lt;br /&gt;
* Betriebsspannung 5V (stabilisiert) &lt;br /&gt;
* Stromaufnahme nur 4mA (typisch) &lt;br /&gt;
* Ultraschallfrequenz 40khz &lt;br /&gt;
* Reichweite 15cm bis 6 Meter &lt;br /&gt;
* Schnittstelle RS232 (TTL) und I2C-Bus &lt;br /&gt;
* Ausgabeeinheit wahlweise mm, inch oder uS &lt;br /&gt;
* Einfachste Verwendung, keine Kalibration/Justierung notwendig&lt;br /&gt;
* Größe 24mm x 20mm x 17mm &lt;br /&gt;
&lt;br /&gt;
[[Bild:srf02_germany.jpg]]&lt;br /&gt;
&lt;br /&gt;
Einige Bascom Programmbeispiele zum SRF02 findet man unter [[Ultraschallsensor SRF02 am RN-Board]]&lt;br /&gt;
&lt;br /&gt;
=== Vergleichstabelle ===&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Blaueschmaltabelle}}&lt;br /&gt;
 |&lt;br /&gt;
 |'''SRF10'''&lt;br /&gt;
 |'''SRF08'''&lt;br /&gt;
 |'''SRF05'''&lt;br /&gt;
 |'''SRF04'''&lt;br /&gt;
 |'''SRF02'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Betr. Spannung'''&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |5V&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Stromaufnahme'''&lt;br /&gt;
 |3mA typ.,&amp;lt;br&amp;gt; 15mA max.&lt;br /&gt;
 |3mA typ.,&amp;lt;br&amp;gt; 15mA max.&lt;br /&gt;
 |4mA typ.,&amp;lt;br&amp;gt; 30mA max.&lt;br /&gt;
 |30mA typ.,&amp;lt;br&amp;gt; 50mA max.&lt;br /&gt;
 |4mA typ.&amp;lt;br&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
 |-&lt;br /&gt;
 |'''US Leistung'''&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |100 – 150mW&lt;br /&gt;
 |?? mW&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Frequenz'''&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |40kHz&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Bereich'''&lt;br /&gt;
 |72&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |55&amp;amp;ordm;&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Reichweite'''&lt;br /&gt;
 |4cm - 6m&lt;br /&gt;
 |3cm - 6m&lt;br /&gt;
 |3cm - 4m&lt;br /&gt;
 |3cm - 3m&lt;br /&gt;
 |15cm - 6m&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Triggerimpuls'''&lt;br /&gt;
 |&lt;br /&gt;
 |&lt;br /&gt;
 |10µs min.&lt;br /&gt;
 |10µs min.&lt;br /&gt;
 |&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Abmessung in mm'''&lt;br /&gt;
 |32 x 15 x 10&lt;br /&gt;
 |43 x 20 x 17&lt;br /&gt;
 |43 x 20 x 17&lt;br /&gt;
 |43 x 20 x 17&lt;br /&gt;
 |24 x 20 x 17&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Interface'''&lt;br /&gt;
 |I2C&lt;br /&gt;
 |I2C&lt;br /&gt;
 |TTL Impuls&lt;br /&gt;
 |TTL Impuls&lt;br /&gt;
 |I2C o. RS232 TTL&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Feature'''&lt;br /&gt;
 |Minimodul&lt;br /&gt;
 |Lichtsensor&lt;br /&gt;
 |SRF04 Modus&lt;br /&gt;
 |&lt;br /&gt;
 |nur 1 US-Kapsel&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Preis ca. *'''&lt;br /&gt;
 |44,00 €&lt;br /&gt;
 |44,00 €&lt;br /&gt;
 |22,00 €&lt;br /&gt;
 |25,00 €&lt;br /&gt;
 |19,00 €&lt;br /&gt;
 |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''*''' Der Preis dient nur zum vergleich untereinander, nicht als Referenz !&lt;br /&gt;
&lt;br /&gt;
==Kompaß== &lt;br /&gt;
===Kompaß-Modul CMPS03===&lt;br /&gt;
Laut der Doku ist diese Modul speziell für die Bedürnisse von Robotern gestaltet worden. Es mißt seine Lage relativ zum Erdmagnetfeld und liefert diesen Wert&lt;br /&gt;
* Als PWM-Signal &lt;br /&gt;
* Über I2C entweder 0-255 als Byte oder&lt;br /&gt;
* 0-3599 als 16-Bit Wert (MSB first)&lt;br /&gt;
&lt;br /&gt;
In der vorliegenden Doku ist eine fixe I2C-Adresse von 0xC0 angegeben. Was leider noch fehlt, sind Angaben, ob und wie diese Adresse geändert werden kann.&lt;br /&gt;
&lt;br /&gt;
Bei waagrechter(!) Montage ist das also ein Kompaß, bei senkrechter Montage dieser Module kann man auch die Neigung in Nord-Süd-Richtung messen. Hierzu sind 2 Module nötig, die zueinander um 90° gedreht angeordnet sein müssen. Die Neigung in Ost-West-Richtung zu messen, ist dagegen leider nicht möglich. Wenn ein CMPS03 als Kompass verwendet werden soll, sind zwei Dinge zu beachten: &lt;br /&gt;
* Mindestens 20 cm Abstand von Eisen(Motore)&lt;br /&gt;
* Exakte horizontale Ausrichtung.&lt;br /&gt;
Eine Montage an einem langen Stab aus Holz oder Kuststoff hoch über dem Roboter ist sinnvoll. &lt;br /&gt;
&lt;br /&gt;
Das Ganze ist eine Anwendung des Philips-KMZ51 Magnet-Feld-Sensors mittels eines PIC16F872&lt;br /&gt;
&lt;br /&gt;
Gelegentlich sollte das Modul kalibriert werden. Das kann über den I2C-Bus, aber auch mittels einen Pins am Modul initiiert werden. Dafür muß am Pin6 für jede Himmelsrichtung einmal kurz GND angelegt werden. Diese 4 Meßpunkte nimmt das Modul auf und speichert sie im EEPROM. &lt;br /&gt;
&lt;br /&gt;
Ein Beispielprogramm findet man hier:&lt;br /&gt;
* [[Bascom und Kompass CMPS03]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:cmps3pin.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Beschleunigung==&lt;br /&gt;
&lt;br /&gt;
Beschleunigungssensoren messen die Beschleunigung, die auf sie wirkt - wenn sie auf dem Tisch liegen, messen sie beispielsweise die Erdbeschleunigung von 1g. In einem Auto können weitere Beschleunigungen hinzukommen: Zur Seite beim Kurvenfahren, nach vorne oder hinten beim Beschleunigen, oder bei zügiger Fahrt über eine Bergkuppe auch mal welche in vertikaler Richtung.&amp;lt;br&amp;gt;&lt;br /&gt;
Beschleunigungssensoren sind meist mehrdimensional ausgelegt, so dass für mehrere Achsen ein Sensor verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Anwendungen finden sie in ESP-Systemen in Autos, die u.a. über die Querbeschleunigung ausrechnen können, ob das Fahrzeug seitlich driftet oder gar schleudert.&amp;lt;br&amp;gt;&lt;br /&gt;
Eine andere wichtige Aufgabe übernehmen sie zusammen mit Gyroskopen in Trägheitsnavigationssystemen, die dann sowohl die Lage im Raum als auch die Bewegung feststellen können.&lt;br /&gt;
&lt;br /&gt;
Moderne Piezo-Sensoren sind nur noch Chip-gross und können direkt in Schaltungen integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele für solche Chips ist die Chipfamilie [[ADXL]] von Analog Devices. Sie umfaßt 1- und 2-Achs Accelerometer in verschiedenen Empfindlichkleiten. Der Test eines solchen Sensors ist hier beschrieben. http://www.roboternetz.de/phpBB2/viewtopic.php?t=8525&lt;br /&gt;
&lt;br /&gt;
==Drehung==&lt;br /&gt;
&lt;br /&gt;
Um Drehungen zu messen, werden sogenannte Gyroskope, kurz &amp;quot;Gyros&amp;quot; verwendet. Typische Vertreter sind hier die [[ADXRS]]-Familie von Analog Devices. Diese sind allerdings, anders als die Beschleunigungssensoren, meistens nur für eine Achse ausgelegt. Die Ausgabe erfolgt meist analog, jede Ausgangsspannung entspricht einer bestimmten Drehrate in °/Sekunde.&lt;br /&gt;
&lt;br /&gt;
Gemessen wird die Auswirkung der Corioleskraft auf zwei gleiche, in Bewegung gehaltene Massen. Diese schwingen radial, d.h. 90° verdreht zu der Achse, auf der die Drehung gemessen werden soll. Wird der Sensor um die Achse gedreht, ändert sich die Geschwindigkeit dieser Massen, da sie auf einer gedachten Scheibe abwechselnd nach innen und außen wandern. Je weiter sie außen sind, desto höher ist ihre Geschwindigkeit, je weiter innen, desto langsamer sind sie. Bei der Bewegung nach außen müssen sie also beschleunigt werden, andersherum genauso. Die dabei auftretenden Beschleunigungen werden mittels einiger Fühler gemessen, die einen Plattenkondensator bilden.&lt;br /&gt;
&lt;br /&gt;
Eine Anwendung sind im Flugmodellbau Gyro-&amp;quot;Taillocks&amp;quot;, die in Hubschraubern die Heckstabilität verbessern und ESP-Systeme in Autos, die u.a. durch die Messung der Gierrate, also der Drehung des Fahrzeugs um die Hochachse, feststellen können, ob das Fahrzeug seitlich driftet oder sogar schleudert.&lt;br /&gt;
&lt;br /&gt;
==Geschwindigkeit==&lt;br /&gt;
&lt;br /&gt;
Geschwindigkeit kann unterschiedlich erfasst werden.&lt;br /&gt;
* Direkt am Rad oder Antrieb. Diese Methode wird häufig auch in KFZ verwendet, stößt jedoch an ihre Grenzen wenn die Räder viel Schlupf haben. &lt;br /&gt;
* Gegenüber der Luft mittels [[Pitot-Tube]]. Das wird bei Flugzeugen so gemacht, oder z.B. in der Formel 1. Bei niedriegen Geschwindigkeiten nicht zu gebrauchen&lt;br /&gt;
* Mittels eines optischen Sensors gegenüber dem Untergrund. Dafür kann ein [[Maussensor]] aus einer optischen Maus verwendent werden, evtl. mit einer Anpassung der Optik für einen geänderten Abstand.&lt;br /&gt;
* Mittels GPS-Empfang. Funktioniert nur unter freiem Himmel.&lt;br /&gt;
Siehe auch unter [[Sensoren für die Geschwindigkeitsmessung]]&lt;br /&gt;
&lt;br /&gt;
==Temperatur== &lt;br /&gt;
===NTCs===&lt;br /&gt;
NTCs (Negative Temperature Coefficient)oder Heißleiter sind stromleitende Materialien, die bei hohen Temperaturen Strom besser leiten als bei tiefen, das heißt, mit steigender Temperatur sinkt ihr elektrischer Widerstand. Siehe auch unter [[NTC]]. Ein großer Vorteil ist die leichte Anwendung und der geringe Preis. Nachteil ist das der Widerstandswert sich nicht linear mit der Temperatur verändert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:ntc.gif]]&lt;br /&gt;
&lt;br /&gt;
===PTCs===&lt;br /&gt;
&lt;br /&gt;
PTCs sind Temperatursensoren, deren Widerstand sich mit steigender Temperatur erhöht. Dazu gehören&lt;br /&gt;
&lt;br /&gt;
*PT100, PT1000 etc.&lt;br /&gt;
*Die KTYxx-xxx Reihe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== KTY: Silizium Temperatursensoren ====&lt;br /&gt;
&lt;br /&gt;
Die KTY-Temperatursensoren sind verglichen mit anderen Temperatursensoren verhältnismäßig günstig, haben dafür aber auch mehr Nachteile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Genauigkeit ist ziemlich eingeschränkt, weshalb die KTY-Temperatursensoren zuerst kalibriert werden sollten. Dies muss Schaltungstechnisch oder in Software erfolgen, eine eingebaute Kalibrierung gibt es nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
Andererseits lassen sich mittels Oversampling sehr hoch aufgelöst Temperaturen messen, was aufgrund mittelmäßiger Linearität (auch nach der Linearisierung) aber nur bei der Messung kleiner Temperaturunterschiede empfehlenswert ist.&amp;lt;br&amp;gt;&lt;br /&gt;
Linearisiert werden die KTY an 5 Volt mit einem Reihenwiderstand von etwa 2,7 kOhm bis 3,3 kOhm.&amp;lt;br&amp;gt; &lt;br /&gt;
http://www.roboternetz.de/phpBB2/viewtopic.php?p=342164&amp;amp;sid=ad63fd51eb08bcf225389af5bbc4fcfd#342164&lt;br /&gt;
&lt;br /&gt;
===LM335 und LM35===&lt;br /&gt;
&lt;br /&gt;
[[Bild:LM335.JPG|center]]&lt;br /&gt;
&lt;br /&gt;
Der Temperatursensor LM335 funktioniert wie eine Z-Diode, die ihre Durchbruchspannung proportional zur Temperatur ändert. Beim Sensor LM335 beträgt diese Änderung 10mV/K, beim Sensor LM35 beträgt die Änderung 10mV/&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C. &lt;br /&gt;
&lt;br /&gt;
Der größte Unterschied zwischen den Sensoren ist der, dass am Ausgang des LM335 bei 0&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C etwa 2,73V anliegen (273K = 0&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C) und beim LM35 0V. Sollen negative Temperaturen gemessen werden, so muss man für den LM35 das Bezugspotential GND anheben (z.B. mit zwei Si-Dioden).&lt;br /&gt;
&lt;br /&gt;
Von den Sensoren LM335 und LM35 gibt es auch noch genauere Ausführungen, welche einen geringeren Temperatur-Fehler ab Werk haben. Diese Versionen heißen LM15/LM25 bzw. LM135/LM235 und sind entsprechend teurer als die 3er Version (zum Vergleich: LM335 kostet bei Reichelt 0,89€, der LM135 jedoch 7,75€). &lt;br /&gt;
&lt;br /&gt;
Der LM335 und LM35 messen nach einer einfachen Kalibrierung mit einem Poti, bis auf 1&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C genau. Dazu muss man mit dem Poti die Ausgangsspannung bei 25&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C auf 2,98V einstellen (2,98V / 0,01V/K = 298K = 25&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C). Da der Sensor über seinen Messbereich  sehr linear ist, braucht man nur bei einer Temperatur Kalibrieren. Durch den Einsatz mehrerer in Reihe geschalteter Sensoren, kann man das Ausgangssignal Verstärken (bei drei LM335 erhält man dann 30mV/K anstatt 10mV/K) oder, wenn die Sensoren im Raum verteilt sind, einen einfachen Mittelwert bilden.&lt;br /&gt;
&lt;br /&gt;
====Beschaltung und Dimensionierung eines LM335====&lt;br /&gt;
[[Bild:lm335schaltung.jpg|center]]&lt;br /&gt;
Da sich der Sensor wie eine Z-Diode verhält, muss der Strom durch diese Begrenzt werden, um eine Verfälschung des Signals oder gar eine Zerstörung zu verhindern. Fließt jedoch zu wenig Strom durch die Diode, so treten Störungen auf und die Genauigkeit sinkt.&lt;br /&gt;
&lt;br /&gt;
Der Strom wird auf einfache weiße, wie bei einer LED, durch einen Widerstand (hier R1) begrenzt. Der Strom sollte zwischen Mindestens 450µA und Maximal 5mA liegen. Bei einer Betriebsspannung von 5V kann also für 2mA ein Widerstand von etwa 2,5kOhm benutzt werden (R = U/I). &lt;br /&gt;
&lt;br /&gt;
Die max. Betriebsspannung sollte 30V nicht überschreiten!&lt;br /&gt;
&lt;br /&gt;
Zur Kalibrierung schließt man an ein 10kOhm Potentiometer zwischen V+ und V- (GND) des Sensors an und legt dessen Schleifer auf den ADJ-Pin. Nun stellt man die Ausgangsspannung in Abhängigkeit von der Raumtemperatur (welche Bekannt sein sollte) ein (1&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C = 1K, 273K = 0&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C). Kalibriert man den LM335 nicht, so kann dieser um bis zu 9K falsch gehen!&lt;br /&gt;
&lt;br /&gt;
Im letzten Bild (ganz rechts) ist die schon angesprochene Reihenschaltung aufgezeichnet. Um ein größeres Ausgangssignal zu erhalten, kann man das Signal auch mit einem [[Operationsverstärker#Verstärker|Operationsverstärker]] Verstärken. Das ist günstiger und man hat die Möglichkeit, das Signal um ein Vielfaches zu Verstärken ohne einige Dutzend Sensoren ein zusetzten!&lt;br /&gt;
&lt;br /&gt;
Pin-Belegungen und weitere Daten finden sich im Datenblatt (kann man z.B. bei Reichelt herunterladen).&lt;br /&gt;
&lt;br /&gt;
===Temperatur-Sensor LM75===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:lm75.gif|center]]&lt;br /&gt;
&lt;br /&gt;
Dieser Chip von National Semiconductors kann die Umgebungstemperatur mit einer Auflösung von 0.5&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt; Grad Celsius messen und wird über einen I2C Bus angesprochen. &lt;br /&gt;
&lt;br /&gt;
Der Messbereich: &lt;br /&gt;
*−25&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bis 100&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bei ±2&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C(max)Genauigkeit.&lt;br /&gt;
*−55&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bis 125&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C bei ±3&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C(max)Genauigkeit. &lt;br /&gt;
&lt;br /&gt;
Der LM75 bietet:&lt;br /&gt;
* Einen Schaltausgang (invertierbar) - z.B. für Ventilator, Heizung etc.&lt;br /&gt;
* Programmierbarer oberer und unterer Schaltpunkt.&lt;br /&gt;
* Schaltausgang alternativ auch als Interrupt verwendbar.&lt;br /&gt;
* Über von außen einstellbare I2C-Adresse. Bit 0 = R/W, Bits 1-3 einstellbar, Bit 4-7 fixe Adresse 0x9n &lt;br /&gt;
* Maximal 8 Stück LM75 an einem I2C Bus. &lt;br /&gt;
&lt;br /&gt;
Durch I2C-Lesebefehle kann man die Temperatur (2x8Bit)auslesen.&lt;br /&gt;
&lt;br /&gt;
Das erste Byte ist der Temperatur Vorkommawert in ganzen Grad, als normales signed char. Das Bit 7 vom zweiten Byte bestimmt den Nachkommawert. Wenn Bit 7 gleich 1 so ist der Nachkommawert + 0.5&amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C. Auch dann + 0.5 &amp;lt;sup&amp;gt;o&amp;lt;/sup&amp;gt;C wenn Vorkommawert negativ. Wenn Bit 7 gleich 0 so ist der Nachkommawert = 0. Bit 0-6 vom zweiten Byte sind ohne Bedeutung.&lt;br /&gt;
&lt;br /&gt;
===Programm-Beispiel für LM75===&lt;br /&gt;
Der LM75 wird über den [[I2C]]-Bus angesprochen.&lt;br /&gt;
In BasCom, wo es ja keine signed char gibt, wird das Interpretieren auf sehr unterschiedliche Art empfohlen. &lt;br /&gt;
&lt;br /&gt;
Ich empfehle:&lt;br /&gt;
&lt;br /&gt;
 dim Ival as integer&lt;br /&gt;
 dim Msb as byte&lt;br /&gt;
 dim Lsb as byte&lt;br /&gt;
         I2cstart&lt;br /&gt;
         I2cwbyte &amp;amp;H91   ' Lese-adresse !  &lt;br /&gt;
         If Err = 1 Then&lt;br /&gt;
            I2cstop       ' kein ACK vom LM75 --&amp;gt; irgendein Fehler&lt;br /&gt;
            Ival = 9999   ' Zeichen, daß der Wert ungültig ist !&lt;br /&gt;
         Else&lt;br /&gt;
            I2crbyte Msb , Ack&lt;br /&gt;
            I2crbyte Lsb , Nack&lt;br /&gt;
            I2cstop&lt;br /&gt;
            If Msb.7 = 1 Then&lt;br /&gt;
               Ival = Makeint(msb , &amp;amp;HFF)   ' auffüllen mit den Vorzeichen bits&lt;br /&gt;
            Else&lt;br /&gt;
               Ival = Makeint(msb , &amp;amp;H00)   ' positiv, also bleibt es so&lt;br /&gt;
            End If&lt;br /&gt;
            Ival = Ival * 10                ' erweitern &lt;br /&gt;
            If Lsb.7 = 1 Then&lt;br /&gt;
              Ival = Ival + 5               ' fünf Zehntel Grad dazu &lt;br /&gt;
            End If&lt;br /&gt;
         End if&lt;br /&gt;
&lt;br /&gt;
Man erhält als Ergebnis die Temperatur in 0,5 Grad Schritten (Natürlich nur, wenn's keine Fehler gab).&lt;br /&gt;
&lt;br /&gt;
Ein weiteres Beispiel [http://www.darc-coburg.de/modules/wiwimod/index.php?page=LM75]&lt;br /&gt;
&lt;br /&gt;
==Resistive Sensoren==&lt;br /&gt;
Resistive Sensoren bzw. Linearpotentiometer arbeiten als Spannungsteiler über einer Hybridleitplastik- schicht und sind in unterschiedlichen Bauformen erhältlich; z.B. für Zylindereinbau, Klemmbock- u. Gelenkaugenbefestigung oder Taster.&lt;br /&gt;
Deren Einsatzgebiete sind vorwiegend in der Industrie.&lt;br /&gt;
&lt;br /&gt;
==Kapazitive Sensoren==&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für kapazitive Sensoren sind Luftfeuchtigkeitsmesser, die ihre Kapazität entsprechend der Luftfeuchtigkeit ändern. Das Auslesen der Kapazität kann prinzipiell über das Ausmessen von Ladekurven geschehen. Dies ist jedoch bei kleinen Kapazitäten nicht praktisch durchführbar, weshalb man in diesem Falle meist einen Schwingkreis baut, dessen Frequenz man dann misst und so dann zusammen mit der bekannten Induktivität der Spule die Kapazität des Kondensators ausrechnen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:feuchtesensor.gif|framed|center|Valvo Feuchtigkeitssensor 10-90% (Kapazität: 122 pF bei TU = 25 °)]]&lt;br /&gt;
&lt;br /&gt;
==Induktive Sensoren==&lt;br /&gt;
Induktiver Näherungsschalter&lt;br /&gt;
&lt;br /&gt;
Sensoren die ihre Induktivität entsprechend der Messgröße ändern können auch mit Hilfe eines Schwingkreises mit bekannter Kapazität ausgemessen werden.&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
==Piezoelektrische Sensoren==&lt;br /&gt;
Hier ist ein Experiment dargestellt das die Funktion von Piezowandlern demonstriert.&lt;br /&gt;
&lt;br /&gt;
Drückt man auf eine längliche Glasplatte (Mikroskopträger Länge 76mm), die an den Enden auf je einem Piezo Wandler gelagert ist, dann ergeben sich Signale, die von den Kräften auf die Wandler abhängig sind. &lt;br /&gt;
&lt;br /&gt;
Die Summe der beiden Kräfte entspricht der Gesamtkraft. Das Verhältnis der beiden Kräfte entspricht dem Verhältnis der Abstände des Druckpunktes zum Wandler. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Piezowandler.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Versuch wurde mit der Frequenz von ca. 4Hz (0,5s/div) von einem Ende bis zum anderen auf die Platte gedrückt. (Tonleiter). Die Signale der beiden Wandler sind im Oszillogramm aufgetragen und die Folge der Druck-Positionen ist auf den ersten Blick schon mal nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
==PIR Passiv Infrarot Sensoren==&lt;br /&gt;
Hier handelt es sich um Passiv-Infrarot-Bewegungsmelder. Bewegungsmelder regieren beim Eintritt einer Person (Tier) in das Erfassungsfeld des Sensors. Die Anwendungsmöglichkeiten sind nahezu unbegrenzt, man kennt die Technik ja von vielen Terrassenlampen, welche sich beim vorbeigehen automatisch einschalten.&lt;br /&gt;
Reagiert wird also auf die Körperwärme einer sich im Erfassungsfeld bewegenden Person.&lt;br /&gt;
[[Bild:pir.jpg|right]]&lt;br /&gt;
Zum Prinzip: &lt;br /&gt;
Wärmestrahlen, die einen Erfassungsvorgang auslösen, liegen im Infrarot-Bereich des Wellenspektrums. In diesem Bereich gibt der menschliche Körper seine Wärmestrahlung ab. Leuchtmittel wie Glüh- , Halogen- und Entladungslampen, die für eine Strahlung im sichtbaren Bereich um 0,555 μm entwickelt wurden, geben jedoch auch einen erheblichen Teil an Wärmestrahlung im Infrarot-Bereich ab.&lt;br /&gt;
Im Spektrum oberhalb des sichtbaren Licht, ab 0,780 μm, beginnt der Infrarot-Bereich. Die Wellenlänge&lt;br /&gt;
dieser IR-Strahlung ist abhängig von der Temperatur eines Körpers. Die Wärmestrahlung&lt;br /&gt;
des Menschen hat ihr Maximum zwischen 9 und 10 μm im Infrarot-Bereich.&lt;br /&gt;
Diese Tatsache nutzt der PIR Sensor mittels sogenannter pyroelektrischer IRDetektoren, welche eine hohe Empfindlichkeit im langwelligen Infrarot-Bereich aufweisen. Die Infrarot-&lt;br /&gt;
Strahlung verhält sich ähnlich wie sichtbares Licht. Sie kann reflektiert und durch Linsen&lt;br /&gt;
gebündelt werden.&lt;br /&gt;
Basis eines solchen IR-Detektors (Sensors) sind Lithium-Tantalatkristalle. Diese Kristalle erzeugen,&lt;br /&gt;
bei Wärmeänderung (positive oder negative Temperaturänderung), eine elektrische Spannung.&lt;br /&gt;
Die von den Kristallen abgegebene Spannung liegt im Bereich von einigen μV (μV = millionstel Volt) und ist von folgenden Bedingungen abhängig: &lt;br /&gt;
* Der Intensität der Wärmequelle (Temperatur und Größe)&lt;br /&gt;
* Dem Umgebungsmedium (Temperatur, unterschiedliche Luftfeuchtigkeit)&lt;br /&gt;
* Der Entfernung zwischen Wärmequelle und IR-Sensor&lt;br /&gt;
* Der Bewegungsgeschwindigkeit und Bewegungsrichtung der Wärmequelle&lt;br /&gt;
* Der Empfindlichkeit des PIR-Elementes (frequenzabhängiges Bandpaßverhalten mit Maximum bei ca. 0,1 Hz)&lt;br /&gt;
&lt;br /&gt;
Zur Unterdrückung von Einflüssen aus der Umgebung (übliche wetterbedingte Temperaturänderungen), sind in jedem Sensor 2 Kristalle antiparallel geschaltet. &lt;br /&gt;
Einer der Kristalle gibt, bei Auftreffen von Wärmestrahlung einen positiven, der andere einen negativen Spannungsimpuls ab. Wärmeänderungen die gleichzeitig und mit gleicher Intensität auf beide Kristalle einwirken lösen so keinen Erfassungsvorgang aus, denn die beiden Impulse heben sich gegenseitig auf. Dadurch ist ein Auslösen bei Wärmeänderungen der Umgebung weitgehend ausgeschlossen.&lt;br /&gt;
Anders verhält es sich bei schnellen Bewegungen. Die Lithiumtantalat-Kristalle geben, entsprechend&lt;br /&gt;
der Bewegung und der dadurch hervorgerufenen Wärmeänderung im Erfassungsfeld, ihre&lt;br /&gt;
Impulse zeitversetzt ab. Die beiden Impulse addieren sich zu einer Wechselgröße mit höherer&lt;br /&gt;
Signalamplitude. Dieses elektrische Ausgangssignal ist proportional der Wärmeänderung und führt zur Meldung einer Bewegung.&lt;br /&gt;
&lt;br /&gt;
==Autoren==&lt;br /&gt;
* [[Benutzer:PicNick|PicNick]]&lt;br /&gt;
* [[Benutzer:Frank|Frank]] &lt;br /&gt;
* [[Benutzer:Dennis.strehl|Dennis.strehl]]&lt;br /&gt;
* [[Benutzer:Florian|Florian]]&lt;br /&gt;
* [[Benutzer:BASTIUniversal|BASTIUniversal]]&lt;br /&gt;
* Topic&lt;br /&gt;
* [[Benutzer:Manf|Manf]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[Navigation]]&lt;br /&gt;
* [[Sensoren]]&lt;br /&gt;
* [[Graycode]]&lt;br /&gt;
* [[Ultraschall SRF10 an RN-Control]]&lt;br /&gt;
* [[Ultraschall SRF05 an RN-MiniControl]]&lt;br /&gt;
* [[Ultraschallsensor SRF02 am RN-Board]]&lt;br /&gt;
* [[Bascom und Kompass CMPS03]]&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
*[http://www.ikm.uni-karlsruhe.de/forschung/pzt_webseiten/de/grundlagen/pyro.html Piezoelektrische Sensoren]&lt;br /&gt;
*[http://www.roboternetz.de/phpBB2/dload.php?action=category&amp;amp;cat_id=2 Datenblätter im Download-Bereich des Roboternetz]&lt;br /&gt;
*[http://www.nxp.com/acrobat_download/various/SC17_GENERAL_TEMP_1996_3.pdf KTY Sensor Datenblatt]&lt;br /&gt;
*[http://www.tranzistoare.ro/datasheets2/83/83853_1.pdf NTC Datenblatt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Robotikeinstieg]]&lt;br /&gt;
[[Category:Grundlagen]]&lt;br /&gt;
[[Category:Elektronik]]&lt;br /&gt;
[[Category:Sensoren]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13883</id>
		<title>Timer/Counter (Avr)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13883"/>
				<updated>2008-08-18T11:39:20Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* PWM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Mikrocontroller der AVR-Familie besitzen je nach Typ eine unterschiedliche Anzahl an programmierbaren [[Timer|Timern]]. Bei den aktuellen ATmegas sind das mindestens ein 8-Bit Timer und bei größeren Ausführungen der Serie auch 16-Bit Timer. Die Timer werden immer Timerx benannt, wobei x für die Timernummer steht (also 0, 1, 2, usw.). &lt;br /&gt;
Die Konfigurationsmöglichkeiten sind von Timer zu Timer unterschiedlich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis:''' Die folgenden Code-Beispiele sind in C programmiert und wurden für einen [[ATMega32|ATmega32]] entwickelt. Sie lassen sich also ohne große Änderungen auch auf anderen Mikrocontrollern der AVR-Familie einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Funktionsweise ==&lt;br /&gt;
Timer funktionieren nach dem allgemeinen Prinzip, dass sie eine Ganzzahl (im weiteren als Zähler bezeichnet) je nach Betriebsmodus auf- oder abwärtszählen, d.h. inkrementieren bzw. dekrementieren.&lt;br /&gt;
&lt;br /&gt;
Angenommen, der Timer arbeitet im einfachsten Betriebsmodus, dem normalen Modus (siehe [[Timer/Counter (Avr)#Normaler Modus (Normal Mode)|Normaler Modus (Normal Mode)]]). Die Zählrichtung des Timers ist aufsteigend gerichtet. Je nach Auflösung, also 8-Bit oder 16-Bit, erreicht der Zähler irgendwann einen bestimmten Zustand. Möglich wäre, dass er überläuft, wenn z.B. bei einem 8-Bit Timer der Wert 255 inkrementiert wird (siehe Grafik).&lt;br /&gt;
&lt;br /&gt;
[[Bild:AbstrakterZaehlvorgang.png]]&lt;br /&gt;
&lt;br /&gt;
== Der Prescaler ==&lt;br /&gt;
Der Prescaler (eng. = Vorteiler) kann dazu genutzt werden, den Takt, der den Timern zugeführt wird, zu verkleinern. U.a. kann man damit die Timer so konfigurieren, damit diese in den unterschiedlichsten Frequenzen takten. Hier eine Grafik die den Prescaler veranschaulicht:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Prescaler.png]]&lt;br /&gt;
&lt;br /&gt;
Das obere Diagramm zeigt den Betrieb ohne Prescaler, das untere mit Prescaler. Die gestrichelte Linie zeigt, wann ein Interrupt eintritt.&lt;br /&gt;
&lt;br /&gt;
Im Teil [[Timer/Counter (Avr)#Die Betriebsmodi|Die Betriebsmodi]] wird weiter auf die praktische Verwendung des Prescalers eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Die Betriebsmodi ==&lt;br /&gt;
Die AVR-Timer können in unterschiedlichen Betriebsmodi betrieben werden. Diese sind:&lt;br /&gt;
* Normaler Modus&lt;br /&gt;
* CTC Modus&lt;br /&gt;
* PWM&lt;br /&gt;
&lt;br /&gt;
=== Normaler Modus (Normal Mode) ===&lt;br /&gt;
Der einfachste Betriebsmodus ist der normale Modus. Er funktioniert wie im Abschnitt  &amp;quot;[[Timer/Counter (Avr)#Allgemeine Funktionsweise|Allgemeine Funktionsweise]]&amp;quot; beschrieben. Die Zählrichtung des Timers ist immer aufsteigend, und irgendwann kommt es zu dem Interrupt Timer-Overflow (welcher in einer passend ISR aufgefangen werden kann). Im einfachsten Fall kann man diesen Modus in folgendem Diagramm darstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1.png]]&lt;br /&gt;
&lt;br /&gt;
Der Zähler des Timers (im Diagramm oben, die aufsteigende und dann wieder zurückgesetzte Linie) ist in dem Register TCNTx gespeichert, wobei x für eine Zahl steht. Soll z.B. auf den Timer0 (siehe Datenblatt des jeweiligen Controllers) des Controllers zugegriffen werden, so ist an TCNT eine 0 anzuhängen, also TCNT0.&lt;br /&gt;
Wie lange es braucht, bis der Zähler einen Overflow auslöst, ist von der Taktfrequenz des Controllers, dem eingestellten Prescaler-Wert und von der Timerauflösung abhängig. Nun wäre es ja sehr unpraktisch, wenn wir den Zähler nicht anpassen könnten. Denn sonst müssten wir unsere Software die den Timer benutzt evtl. anpassen und viel rechnen um z.B. für 1000 ms zu schlafen. Deswegen kann auf den Zähler zugreifen und ihn vorladen bevor dieser wieder vom eigentlichen Timer hochgezählt wird. Dies veranschaulicht folgendes Diagramm:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1_Vorladen.png]]&lt;br /&gt;
&lt;br /&gt;
Dadurch kann man den Timer beeinflussen, und beeinflussen wie lange es dauert, bis ein Overflow auftritt. Um zu berechnen, welchen Wert wir vorladen müssen, kann man auch ein Java-Applet nutzen, siehe unter [[Timer/Counter (Avr)#Weblinks|Weblinks Java Applet]].&lt;br /&gt;
&lt;br /&gt;
Natürlich kann man das auch &amp;quot;von Hand&amp;quot; rechnen. Die Berechnung des Preloader- sowie Prescalerwerts bei Verwendung der Overflow-Interrupts, eines Prescalers von 64 (nicht alle Prescaler können verwendet werden) und eines Quarzes mit der Frequenz von 8 MHz sieht folgendermaßen aus (gesuchte Frequenz beträgt 1000 Hz unter der Verwendung des Timer0 eines ATmega32):&lt;br /&gt;
# &amp;lt;math&amp;gt;Prescale = Frequenz * 1000000 [Hz] = 8000000&amp;lt;/math&amp;gt;&lt;br /&gt;
# Wir definieren den maximalen Zählerwert. Dieser ist bei einem 8-Bit Timer 256, bei einem 16-Bit Timer 65536. In unserem Fall ist der maximale Zählerwert 256, weil Timer0 verwendet wird.&lt;br /&gt;
# Nun wird die Variable ''Prescale'' (s.o.) durch den verwendeten Prescaler (64) geteilt (&amp;lt;math&amp;gt;8000000 Hz / 64 = 125000&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Als nächstes wird der im dritten Punkt errechnete Wert durch die gesuchte Frequenz geteilt &amp;lt;math&amp;gt;=125000 / 1000Hz = 125&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird mathematisch überprüft, ob der errechnete Wert aus dem vierten Punkt kleiner als der maximale Zählerwert ist. Trifft dies zu, so subtrahiert man den errechneten Wert vom maximalen Zählerwert (&amp;lt;math&amp;gt;= 256 - 125 = 131&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Damit haben wir den Wert errechnet, der bei jedem Interrupt, den der Timer0 auslöst, in TCNTx (in diesem Fall TCNT0) nachgeladen werden muss, damit die Interrupts in dem gewünschten Zeitabstand von einer Millisekunde ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
Allerdings bleibt zu bemerken, dass bei der Verwendung einer &amp;quot;ungeraden&amp;quot; Quarzfrequenz (z.B. 7,3728 MHz) der Timer mit einer bestimmten Ungenauigkeit arbeitet. Würden wir z.B. den Quarz oben mit einem Quarz mit 7,3728 MHz austauschen, so wäre die Fehlerrate 0,17%. Diese Ungeauigkeit varriert von verwendetem Prescaler zu Prescaler. D.h. wenn wir einen Prescaler von 1024 (und einer Quarzfrequenz von 8 MHz) verwendet hätten, so hätten wir eine inakzeptable Ungeauigkeit von 11,61%. Deswegen sollte sie eines der genannten Programme unter [[Avr#Weblinks]] verwenden, denn diese zeigen nur die bestmögliche Konfiguration an.&lt;br /&gt;
&lt;br /&gt;
Die Fehlerrate kann natürlich auch ausgerechnet werden. Hier die Rechenschritte (sie sind erweiternd zu der oberen Berechnung):&lt;br /&gt;
# Als erstes wird mathematisch überprüft, ob der Preloaderwert (siehe fünften Schritt oben) größer als 1 ist.&lt;br /&gt;
# Trifft dies zu, so wird als nächstes die resultierende Frequenz errechnet. Die geschieht folgendermaßen: Der errechnete Preloaderwert aus der Rechnung oben wird vom maximalen Zählerwert subtrahiert, anschließend mit dem Prescaler multipliziert und dann das Ganze durch die Variable Prescale geteilt &lt;br /&gt;
&amp;lt;math&amp;gt;(256 - 131) \cdot 64 / 8\,000\,000 \mathrm{Hz} \cdot 1\,000\,000 = 1000&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird die gesuchte Frequenz vom errechneten Wert aus dem dritten Punkt subtrahiert und dann wiederum durch diese geteilt &amp;lt;math&amp;gt;(1000-1000) / 1000 = 0&amp;lt;/math&amp;gt;. Damit läuft dieser Timer genau mit einer Fehlerrate von 0 %.&lt;br /&gt;
&lt;br /&gt;
Betreibt man den Timer im Overflow-Modus, so muss man, wie bereits erwähnt, nach/bei jedem Overflow-Interrupt den Timer nachladen. Der Interrupt heißt in diesem Fall SIG_OVERFLOWx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine&lt;br /&gt;
Frequenz von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und&lt;br /&gt;
einem Preloader von  183 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_SIG_OVERFLOW2)&lt;br /&gt;
{&lt;br /&gt;
	countTimer2++;&lt;br /&gt;
	TCNT2 = 183;		// Nachladen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22);		// Prescaler von 1&lt;br /&gt;
TCNT2  = 183;			// Vorladen&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;TOIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep (uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Allerdings wird auf diese leicht veraltete Technik nun nicht weiter eingegangen. Der Artikel wendet sich nun dem neueren &amp;quot;Compare Output&amp;quot;-Betriebsmodus zu.&lt;br /&gt;
&lt;br /&gt;
Beim &amp;quot;Compare Output&amp;quot;-Betriebsmodus wird genauso ein Zähler hochgezählt. Allerdings wird der Zählerwert nach jeder Inkrementierung mit einem vom Benutzer festgelegten Wert verglichen. Entspricht der Zählerwert dem gespeicherten Wert, so kommt es zu einem Interrupt. Dieser Wert wird in das Register OCRx (x steht wieder für die Timernummer) gespeichert. Je nach Auflösung des Timers ist dieses Register 8-Bit oder 16-Bit breit. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Siehe CTC Modus unten. Dieser wird benötigt um den Timer entsprechend im &amp;quot;Compare Output&amp;quot;-Betriebsmodus vernünftig zu betreiben.&lt;br /&gt;
&lt;br /&gt;
Hier ein typisches Diagramm dieses Betriebsmodus (Hinweis: Das Diagramm wurde unter Verwendung des CTC Modus erstellt. Für Begriffserklärung siehe CTC Modus):&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
Das Ausrechnen des Werts, der in OCRx geschrieben werden muss, damit Frequenz x entsteht, ist nicht sonderlich schwer. Man geht wie bei der Berechnung des Werts für den Overflow-Modus vor (s.o.) nur daß man das resultierende Ergebnis vom maximalen Zählerwert (bei 8-Bit Auflösung ist dieser 256, bei 16-Bit Auflösung 65536) subtrahiert. Das Ergebnis wird dann einmalig in das Register OCRx geschrieben. Mann muss also nicht wie beim Overflow-Modus den Timer nach jedem Interrupt nachladen. Der enstehende Interrupt heißt in diesem Fall SIG_OUTPUT_COMPAREx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Wiederum zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine Frequenz&lt;br /&gt;
von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und einem OCR2-Wert&lt;br /&gt;
von 73 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE2)&lt;br /&gt;
{&lt;br /&gt;
  countTimer2++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22) | (1&amp;lt;&amp;lt;WGM21);	// Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)&lt;br /&gt;
OCR2  = 73;			// Vergleichswert&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;OCIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep(uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CTC Modus (Clear Timer on Compare Match mode) ===&lt;br /&gt;
Der CTC Modus ist eine Erweiterung des &amp;quot;Compare Output&amp;quot;-Betriebsmodus. Der CTC Modus wird z.B. für das obere Beispielprogramm benötigt. Wird der Timer nämlich im normalen Betriebsmodus betrieben, so ist seine Zählergrenze je nach Auflösung 255 oder entsprechend für die 16-Bit Timer. Erst wenn diese Grenze erreicht wurde, wird der Timer zurückgesetzt (also auf 0). Durch den CTC Modus wird der Timer augenblicklich automatisch zurückgesetzt nachdem der Vergleichswert erreicht ist. Man kann also die maximalen Zählergrenze selber definieren.&lt;br /&gt;
Dieses Diagramm veranschaulicht den CTC Modus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== PWM ===&lt;br /&gt;
&lt;br /&gt;
Eine häufige Aufgabe für Mikrocontroller ist die Erzeugung von [[PWM]]-Signalen, zum Beispiel für Motorsteuerungen. Daher sind in den meisten [[AVR|AVRs]] PWM-Einheiten als Hardware vorhanden. Sie sind direkt mit den Timern verbunden und nutzen diese als Taktquelle. Die Hardware-PWM-Einheiten haben den Vorteil, sehr wenig Rechenzeit in Anspruch zu nehmen. Man muss nur die PWM aktivieren und bei Änderungen den gewünschten Wert in ein Register schreiben. Der Rest läuft automatisch und unabhängig vom restlichen Programm, ohne den AVR ständig zu beschäftigen wie bei einer PWM-Lösung in Software. Allerdings stehen meist nur zwei bis drei solcher PWM-Kanäle zur Verfügung, die außerdem an bestimmte Pins gebunden sind. Für die meisten Roboter mit zwei Antriebsmotoren reicht dies aber für gewöhnlich aus. &lt;br /&gt;
&lt;br /&gt;
==== nutzbare Pins am AVR ====&lt;br /&gt;
Die Hardware-PWM-Funktion steht nur an bestimmten Pins zur Verfügung. In der Pinbelegungsübersicht im Datenblatt erkennt man sie daran, dass als Sonderfunktion in Klammern &amp;quot;OC...&amp;quot; angegeben ist. Beim Mega32 sind dies zb. OC0 an PB0, OC1A an PD5, OC1B an PD4 und OC2 an PD7. Der Mega32 hat also insgesamt vier Hardware-PWM-Kanäle. Die Zahl hinter dem &amp;quot;OC&amp;quot; gibt an, zu welchem der Timer dieser PWM-Kanal gehört. Wenn noch ein Buchstabe dahinter kommt, dann gehören mehrere PWMs zu diesem Timer. Beim Mega32 sind also OC1A und OC1B demselben Timer, nämlich Timer1, zugeordnet.&lt;br /&gt;
&lt;br /&gt;
'''Zu beachten ist, dass die für die PWM benutzten Pins zuvor explizit als Ausgang konfiguriert werden müssen! Ansonsten gelangt das PWM-Signal nicht nach draußen!'''&lt;br /&gt;
&lt;br /&gt;
==== Funktionsprinzip ====&lt;br /&gt;
Das &amp;quot;OC&amp;quot; in den Pinbezeichnungen steht für &amp;quot;Output Compare Unit&amp;quot;, also frei übersetzt Ausgangs-Vergleicher-Einheit. Dies beschreibt die Funktionsweise der PWM-Kanäle: der Zählerstand des Timers wird fortlaufend mit einen einstellbaren Referenzwert verglichen, und wenn beide Werte übereinstimmen, kann ein Ausgangspin des AVRs automatisch geschaltet werden (und ein Interrupt ausgelöst werden, was allerdings für die PWM-Funktion nicht relevant ist). Dies entspricht dem Verfahren im [[PWM#PWM_per_Software|Beispiel zur Software-PWM]]. Es läuft nun allerdings vollautomatisch im Hintergrund, sodass der Controller nicht damit belastet wird.&lt;br /&gt;
&lt;br /&gt;
==== Die verschiedenen PWM-Modi ====&lt;br /&gt;
Es gibt -je nach AVR und Timer- etliche Betriebsarten, in denen die PWM-Einheit betrieben werden kann. Sie unterscheiden sich vor allem darin, wie schnell und mit welchen Nebeneffekten sich Änderungen des Sollwertes auf das Ausgangssignal auswirken. Für den Anfang sind diese Unterschiede erst einmal nebensächlich, und für eine einfache Motorsteuerung meist auch irrelevant. Daher wird hier zunächst der &amp;quot;Fast PWM Mode&amp;quot; (&amp;quot;Schneller PWM Modus&amp;quot;, weil hier die größte Ausgangsfrequenz möglich ist) beschreiben, welcher der einfachste von allen ist.&lt;br /&gt;
&lt;br /&gt;
Hierbei zählt der Timer immer von Null an aufwärts, bis er den Maximalwert (teilweise einstellbar) erreicht hat. Dann läuft er über und fängt von vorne an. Wie schnell dies geschieht, wird, wie im normalen Modus, über den Prescaler eingestellt.&lt;br /&gt;
Der gewünschte PWM-Ausgangswert wird im &amp;quot;OCRn&amp;quot;-Register abgelegt. Er darf zwischen Null und dem Maximalwert des Timers liegen. Er wird nun mit dem Timer-Wert verglichen. Was dann passiert, regeln die &amp;quot;COM...&amp;quot;-Bits. Sie bestimmen, wie der Ausgang geschaltet wird. Die übliche Konfiguration ist, dass bei Erreichen des Sollwertes die Ausgänge auf high geschaltet werden, und beim Überlauf auf low. Damit ergibt sich ein nichtinvertiertes PWM-Signal. Schließt man (über einem passenden Motortreiber!) einen Motor an, dreht er sich bei einem Sollwert von 0 gar nicht und beim Maximalwert mit voller Geschwindigkeit.&lt;br /&gt;
&lt;br /&gt;
Beispielcode für den Timer1 des Mega16/32 (und vieler anderer AVRs): &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt; //Warteschleife für die Demo-Ausgabe. Für die eigentliche PWM nicht benötigt!  &lt;br /&gt;
&lt;br /&gt;
/*  PWM-Beispiel für Mega16/32 (beiden haben den gleichen Timer)&lt;br /&gt;
	Benutzt wird Timer1 im Fast PWM Mode, 8 Bit Auflösung&lt;br /&gt;
	Die PWM-Signale liegen auf PD5/OC1A und PD4/OC1B&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
// 1. Den Prescaler einstellen, der die Frequenz festlegt&lt;br /&gt;
	TCCR1B |= (1&amp;lt;&amp;lt;CS12); //Prescaler 256&lt;br /&gt;
	&lt;br /&gt;
// 2. Den Timer in den Fast PWM Mode, 8 Bit schalten&lt;br /&gt;
//ACHTUNG: Die WGM-Bits sind auf beide Konfigurationsregister verteiltt!&lt;br /&gt;
	TCCR1A |= (1&amp;lt;&amp;lt;WGM10);&lt;br /&gt;
	TCCR1B |= (1&amp;lt;&amp;lt;WGM12);&lt;br /&gt;
	&lt;br /&gt;
// 3. Compare Output mode einstellen: Pin geht auf high bei Compare match, auf low bei Überlauf. Ergibt nichtinvertierte PWM.	&lt;br /&gt;
	TCCR1A |= (1&amp;lt;&amp;lt;COM1A1) | (1&amp;lt;&amp;lt;COM1B1) ;	&lt;br /&gt;
	&lt;br /&gt;
// In diesen Registern wird der gwünschte PWM-Wert abgelegt. Erlaubter Bereich: 0 bis 255.&lt;br /&gt;
	OCR1A =	0;&lt;br /&gt;
	OCR1B = 0;	&lt;br /&gt;
&lt;br /&gt;
// 4. Zuletzt die Pins als Ausgänge konfigurieren. Erst jetzt liegt das PWM-Signal an den Pins an!	&lt;br /&gt;
	DDRD |= (1&amp;lt;&amp;lt;PD4) | (1&amp;lt;&amp;lt; PD5);&lt;br /&gt;
&lt;br /&gt;
/*Nun ist der PWM-Modus aktiv! Der Ausgangswert kann nun über die Register OCR1A und OCR1B vorgegeben werden. &lt;br /&gt;
Man könnte ihnen per define noch einen Zweitnamen verpassen, zb */&lt;br /&gt;
#define MotorLinks OCR1A&lt;br /&gt;
#define MotorRechts OCR1B&lt;br /&gt;
//Und nun kann man per &lt;br /&gt;
MotorLinks = 127;&lt;br /&gt;
MotorRechts = 127;&lt;br /&gt;
//seinen Roboter mit halber Kraft vorwärts fahren lassen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*PWM-Demo: Die PWM-Werte werden erst bis zum Maximalwert erhöht und dann wieder verringert. &lt;br /&gt;
Ein angeschlossener Motor wird beschleunigen und dann  wieder abbremsen. */&lt;br /&gt;
	uint8_t wert;&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		for (wert=0; wert&amp;lt;255; wert++)&lt;br /&gt;
			{&lt;br /&gt;
				OCR1A =	wert;&lt;br /&gt;
				OCR1B = wert;&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
	&lt;br /&gt;
		for (wert=255; wert&amp;gt;0; wert--)&lt;br /&gt;
			{&lt;br /&gt;
				OCR1A =	wert;&lt;br /&gt;
				OCR1B = wert;&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}	&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind also vier Einstellungen zu treffen:&lt;br /&gt;
# Takt anlegen per Prescaler&lt;br /&gt;
# PWM-Modus wählen&lt;br /&gt;
# Ausgangs-Aktion festlegen&lt;br /&gt;
# Pins als Ausgänge schalten&lt;br /&gt;
&lt;br /&gt;
Diese Schritte müssen bei jedem AVR-PWM-Kanal ausgeführt werden. Die genauen Registernamen und Werte können sich jedoch je nach Timer-Ausführung etwas unterscheiden.&lt;br /&gt;
&lt;br /&gt;
== Registerübersicht ==&lt;br /&gt;
''Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.''&lt;br /&gt;
&lt;br /&gt;
{| {{Blaueschmaltabelle}} width=100%&lt;br /&gt;
 |'''TIMSK'''&lt;br /&gt;
 |-&lt;br /&gt;
 |Mit diesem Register, der von allen Timern verwendet wird, lässt sich die Interruptausführung und Art des jeweiligen Timers bestimmen.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Registertabelle8Bit|OCIE2|TOIE2|TICIE1|OCIE1A|OCIE1B|TOIE1|OCIE0|TOIE0}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
*'''OCIE2 (Timer/Counter2 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE2 (Timer/Counter2 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TICIE1 (Timer/Counter1, Input Capture Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Input Capture Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1A (Timer/Counter1 Output Compare A Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare A Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1B (Timer/Counter1 Output Compare B Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare B Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE1 (Timer/Counter1 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE0 (Timer/Counter0 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Overflow Interrupt aktiviert  (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Atmel]]&lt;br /&gt;
* [[HEX Beispiel-Dateien für AVR]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]&lt;br /&gt;
* [https://mpg.dnsalias.com/~magerlu/rn-wiki/avrtimer_applet Java Applet Timer Berechnung] &lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Elektronik]]&lt;br /&gt;
[[Kategorie:Abkürzung|AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13882</id>
		<title>Timer/Counter (Avr)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13882"/>
				<updated>2008-08-18T11:36:55Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* PWM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Mikrocontroller der AVR-Familie besitzen je nach Typ eine unterschiedliche Anzahl an programmierbaren [[Timer|Timern]]. Bei den aktuellen ATmegas sind das mindestens ein 8-Bit Timer und bei größeren Ausführungen der Serie auch 16-Bit Timer. Die Timer werden immer Timerx benannt, wobei x für die Timernummer steht (also 0, 1, 2, usw.). &lt;br /&gt;
Die Konfigurationsmöglichkeiten sind von Timer zu Timer unterschiedlich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis:''' Die folgenden Code-Beispiele sind in C programmiert und wurden für einen [[ATMega32|ATmega32]] entwickelt. Sie lassen sich also ohne große Änderungen auch auf anderen Mikrocontrollern der AVR-Familie einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Funktionsweise ==&lt;br /&gt;
Timer funktionieren nach dem allgemeinen Prinzip, dass sie eine Ganzzahl (im weiteren als Zähler bezeichnet) je nach Betriebsmodus auf- oder abwärtszählen, d.h. inkrementieren bzw. dekrementieren.&lt;br /&gt;
&lt;br /&gt;
Angenommen, der Timer arbeitet im einfachsten Betriebsmodus, dem normalen Modus (siehe [[Timer/Counter (Avr)#Normaler Modus (Normal Mode)|Normaler Modus (Normal Mode)]]). Die Zählrichtung des Timers ist aufsteigend gerichtet. Je nach Auflösung, also 8-Bit oder 16-Bit, erreicht der Zähler irgendwann einen bestimmten Zustand. Möglich wäre, dass er überläuft, wenn z.B. bei einem 8-Bit Timer der Wert 255 inkrementiert wird (siehe Grafik).&lt;br /&gt;
&lt;br /&gt;
[[Bild:AbstrakterZaehlvorgang.png]]&lt;br /&gt;
&lt;br /&gt;
== Der Prescaler ==&lt;br /&gt;
Der Prescaler (eng. = Vorteiler) kann dazu genutzt werden, den Takt, der den Timern zugeführt wird, zu verkleinern. U.a. kann man damit die Timer so konfigurieren, damit diese in den unterschiedlichsten Frequenzen takten. Hier eine Grafik die den Prescaler veranschaulicht:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Prescaler.png]]&lt;br /&gt;
&lt;br /&gt;
Das obere Diagramm zeigt den Betrieb ohne Prescaler, das untere mit Prescaler. Die gestrichelte Linie zeigt, wann ein Interrupt eintritt.&lt;br /&gt;
&lt;br /&gt;
Im Teil [[Timer/Counter (Avr)#Die Betriebsmodi|Die Betriebsmodi]] wird weiter auf die praktische Verwendung des Prescalers eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Die Betriebsmodi ==&lt;br /&gt;
Die AVR-Timer können in unterschiedlichen Betriebsmodi betrieben werden. Diese sind:&lt;br /&gt;
* Normaler Modus&lt;br /&gt;
* CTC Modus&lt;br /&gt;
* PWM&lt;br /&gt;
&lt;br /&gt;
=== Normaler Modus (Normal Mode) ===&lt;br /&gt;
Der einfachste Betriebsmodus ist der normale Modus. Er funktioniert wie im Abschnitt  &amp;quot;[[Timer/Counter (Avr)#Allgemeine Funktionsweise|Allgemeine Funktionsweise]]&amp;quot; beschrieben. Die Zählrichtung des Timers ist immer aufsteigend, und irgendwann kommt es zu dem Interrupt Timer-Overflow (welcher in einer passend ISR aufgefangen werden kann). Im einfachsten Fall kann man diesen Modus in folgendem Diagramm darstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1.png]]&lt;br /&gt;
&lt;br /&gt;
Der Zähler des Timers (im Diagramm oben, die aufsteigende und dann wieder zurückgesetzte Linie) ist in dem Register TCNTx gespeichert, wobei x für eine Zahl steht. Soll z.B. auf den Timer0 (siehe Datenblatt des jeweiligen Controllers) des Controllers zugegriffen werden, so ist an TCNT eine 0 anzuhängen, also TCNT0.&lt;br /&gt;
Wie lange es braucht, bis der Zähler einen Overflow auslöst, ist von der Taktfrequenz des Controllers, dem eingestellten Prescaler-Wert und von der Timerauflösung abhängig. Nun wäre es ja sehr unpraktisch, wenn wir den Zähler nicht anpassen könnten. Denn sonst müssten wir unsere Software die den Timer benutzt evtl. anpassen und viel rechnen um z.B. für 1000 ms zu schlafen. Deswegen kann auf den Zähler zugreifen und ihn vorladen bevor dieser wieder vom eigentlichen Timer hochgezählt wird. Dies veranschaulicht folgendes Diagramm:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1_Vorladen.png]]&lt;br /&gt;
&lt;br /&gt;
Dadurch kann man den Timer beeinflussen, und beeinflussen wie lange es dauert, bis ein Overflow auftritt. Um zu berechnen, welchen Wert wir vorladen müssen, kann man auch ein Java-Applet nutzen, siehe unter [[Timer/Counter (Avr)#Weblinks|Weblinks Java Applet]].&lt;br /&gt;
&lt;br /&gt;
Natürlich kann man das auch &amp;quot;von Hand&amp;quot; rechnen. Die Berechnung des Preloader- sowie Prescalerwerts bei Verwendung der Overflow-Interrupts, eines Prescalers von 64 (nicht alle Prescaler können verwendet werden) und eines Quarzes mit der Frequenz von 8 MHz sieht folgendermaßen aus (gesuchte Frequenz beträgt 1000 Hz unter der Verwendung des Timer0 eines ATmega32):&lt;br /&gt;
# &amp;lt;math&amp;gt;Prescale = Frequenz * 1000000 [Hz] = 8000000&amp;lt;/math&amp;gt;&lt;br /&gt;
# Wir definieren den maximalen Zählerwert. Dieser ist bei einem 8-Bit Timer 256, bei einem 16-Bit Timer 65536. In unserem Fall ist der maximale Zählerwert 256, weil Timer0 verwendet wird.&lt;br /&gt;
# Nun wird die Variable ''Prescale'' (s.o.) durch den verwendeten Prescaler (64) geteilt (&amp;lt;math&amp;gt;8000000 Hz / 64 = 125000&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Als nächstes wird der im dritten Punkt errechnete Wert durch die gesuchte Frequenz geteilt &amp;lt;math&amp;gt;=125000 / 1000Hz = 125&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird mathematisch überprüft, ob der errechnete Wert aus dem vierten Punkt kleiner als der maximale Zählerwert ist. Trifft dies zu, so subtrahiert man den errechneten Wert vom maximalen Zählerwert (&amp;lt;math&amp;gt;= 256 - 125 = 131&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Damit haben wir den Wert errechnet, der bei jedem Interrupt, den der Timer0 auslöst, in TCNTx (in diesem Fall TCNT0) nachgeladen werden muss, damit die Interrupts in dem gewünschten Zeitabstand von einer Millisekunde ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
Allerdings bleibt zu bemerken, dass bei der Verwendung einer &amp;quot;ungeraden&amp;quot; Quarzfrequenz (z.B. 7,3728 MHz) der Timer mit einer bestimmten Ungenauigkeit arbeitet. Würden wir z.B. den Quarz oben mit einem Quarz mit 7,3728 MHz austauschen, so wäre die Fehlerrate 0,17%. Diese Ungeauigkeit varriert von verwendetem Prescaler zu Prescaler. D.h. wenn wir einen Prescaler von 1024 (und einer Quarzfrequenz von 8 MHz) verwendet hätten, so hätten wir eine inakzeptable Ungeauigkeit von 11,61%. Deswegen sollte sie eines der genannten Programme unter [[Avr#Weblinks]] verwenden, denn diese zeigen nur die bestmögliche Konfiguration an.&lt;br /&gt;
&lt;br /&gt;
Die Fehlerrate kann natürlich auch ausgerechnet werden. Hier die Rechenschritte (sie sind erweiternd zu der oberen Berechnung):&lt;br /&gt;
# Als erstes wird mathematisch überprüft, ob der Preloaderwert (siehe fünften Schritt oben) größer als 1 ist.&lt;br /&gt;
# Trifft dies zu, so wird als nächstes die resultierende Frequenz errechnet. Die geschieht folgendermaßen: Der errechnete Preloaderwert aus der Rechnung oben wird vom maximalen Zählerwert subtrahiert, anschließend mit dem Prescaler multipliziert und dann das Ganze durch die Variable Prescale geteilt &lt;br /&gt;
&amp;lt;math&amp;gt;(256 - 131) \cdot 64 / 8\,000\,000 \mathrm{Hz} \cdot 1\,000\,000 = 1000&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird die gesuchte Frequenz vom errechneten Wert aus dem dritten Punkt subtrahiert und dann wiederum durch diese geteilt &amp;lt;math&amp;gt;(1000-1000) / 1000 = 0&amp;lt;/math&amp;gt;. Damit läuft dieser Timer genau mit einer Fehlerrate von 0 %.&lt;br /&gt;
&lt;br /&gt;
Betreibt man den Timer im Overflow-Modus, so muss man, wie bereits erwähnt, nach/bei jedem Overflow-Interrupt den Timer nachladen. Der Interrupt heißt in diesem Fall SIG_OVERFLOWx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine&lt;br /&gt;
Frequenz von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und&lt;br /&gt;
einem Preloader von  183 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_SIG_OVERFLOW2)&lt;br /&gt;
{&lt;br /&gt;
	countTimer2++;&lt;br /&gt;
	TCNT2 = 183;		// Nachladen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22);		// Prescaler von 1&lt;br /&gt;
TCNT2  = 183;			// Vorladen&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;TOIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep (uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Allerdings wird auf diese leicht veraltete Technik nun nicht weiter eingegangen. Der Artikel wendet sich nun dem neueren &amp;quot;Compare Output&amp;quot;-Betriebsmodus zu.&lt;br /&gt;
&lt;br /&gt;
Beim &amp;quot;Compare Output&amp;quot;-Betriebsmodus wird genauso ein Zähler hochgezählt. Allerdings wird der Zählerwert nach jeder Inkrementierung mit einem vom Benutzer festgelegten Wert verglichen. Entspricht der Zählerwert dem gespeicherten Wert, so kommt es zu einem Interrupt. Dieser Wert wird in das Register OCRx (x steht wieder für die Timernummer) gespeichert. Je nach Auflösung des Timers ist dieses Register 8-Bit oder 16-Bit breit. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Siehe CTC Modus unten. Dieser wird benötigt um den Timer entsprechend im &amp;quot;Compare Output&amp;quot;-Betriebsmodus vernünftig zu betreiben.&lt;br /&gt;
&lt;br /&gt;
Hier ein typisches Diagramm dieses Betriebsmodus (Hinweis: Das Diagramm wurde unter Verwendung des CTC Modus erstellt. Für Begriffserklärung siehe CTC Modus):&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
Das Ausrechnen des Werts, der in OCRx geschrieben werden muss, damit Frequenz x entsteht, ist nicht sonderlich schwer. Man geht wie bei der Berechnung des Werts für den Overflow-Modus vor (s.o.) nur daß man das resultierende Ergebnis vom maximalen Zählerwert (bei 8-Bit Auflösung ist dieser 256, bei 16-Bit Auflösung 65536) subtrahiert. Das Ergebnis wird dann einmalig in das Register OCRx geschrieben. Mann muss also nicht wie beim Overflow-Modus den Timer nach jedem Interrupt nachladen. Der enstehende Interrupt heißt in diesem Fall SIG_OUTPUT_COMPAREx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Wiederum zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine Frequenz&lt;br /&gt;
von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und einem OCR2-Wert&lt;br /&gt;
von 73 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE2)&lt;br /&gt;
{&lt;br /&gt;
  countTimer2++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22) | (1&amp;lt;&amp;lt;WGM21);	// Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)&lt;br /&gt;
OCR2  = 73;			// Vergleichswert&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;OCIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep(uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CTC Modus (Clear Timer on Compare Match mode) ===&lt;br /&gt;
Der CTC Modus ist eine Erweiterung des &amp;quot;Compare Output&amp;quot;-Betriebsmodus. Der CTC Modus wird z.B. für das obere Beispielprogramm benötigt. Wird der Timer nämlich im normalen Betriebsmodus betrieben, so ist seine Zählergrenze je nach Auflösung 255 oder entsprechend für die 16-Bit Timer. Erst wenn diese Grenze erreicht wurde, wird der Timer zurückgesetzt (also auf 0). Durch den CTC Modus wird der Timer augenblicklich automatisch zurückgesetzt nachdem der Vergleichswert erreicht ist. Man kann also die maximalen Zählergrenze selber definieren.&lt;br /&gt;
Dieses Diagramm veranschaulicht den CTC Modus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
=== PWM ===&lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Eine häufige Aufgabe für Mikrocontroller ist die Erzeugung von [[PWM]]-Signalen, zum Beispiel für Motorsteuerungen. Daher sind in den meisten [[AVR|AVRs]] PWM-Einheiten als Hardware vorhanden. Sie sind direkt mit den Timern verbunden und nutzen diese als Taktquelle. Die Hardware-PWM-Einheiten haben den Vorteil, sehr wenig Rechenzeit in Anspruch zu nehmen. Man muss nur die PWM aktivieren und bei Änderungen den gewünschten Wert in ein Register schreiben. Der Rest läuft automatisch und unabhängig vom restlichen Programm, ohne den AVR ständig zu beschäftigen wie bei einer PWM-Lösung in Software. Allerdings stehen meist nur zwei bis drei solcher PWM-Kanäle zur Verfügung, die außerdem an bestimmte Pins gebunden sind. Für die meisten Roboter mit zwei Antriebsmotoren reicht dies aber für gewöhnlich aus. &lt;br /&gt;
&lt;br /&gt;
==== nutzbare Pins am AVR ====&lt;br /&gt;
Die Hardware-PWM-Funktion steht nur an bestimmten Pins zur Verfügung. In der Pinbelegungsübersicht im Datenblatt erkennt man sie daran, dass als Sonderfunktion in Klammern &amp;quot;OC...&amp;quot; angegeben ist. Beim Mega32 sind dies zb. OC0 an PB0, OC1A an PD5, OC1B an PD4 und OC2 an PD7. Der Mega32 hat also insgesamt vier Hardware-PWM-Kanäle. Die Zahl hinter dem &amp;quot;OC&amp;quot; gibt an, zu welchem der Timer dieser PWM-Kanal gehört. Wenn noch ein Buchstabe dahinter kommt, dann gehören mehrere PWMs zu diesem Timer. Beim Mega32 sind also OC1A und OC1B demselben Timer, nämlich Timer1, zugeordnet.&lt;br /&gt;
&lt;br /&gt;
'''Zu beachten ist, dass die für die PWM benutzten Pins zuvor explizit als Ausgang konfiguriert werden müssen! Ansonsten gelangt das PWM-Signal nicht nach draußen!'''&lt;br /&gt;
&lt;br /&gt;
==== Funktionsprinzip ====&lt;br /&gt;
Das &amp;quot;OC&amp;quot; in den Pinbezeichnungen steht für &amp;quot;Output Compare Unit&amp;quot;, also frei übersetzt Ausgangs-Vergleicher-Einheit. Dies beschreibt die Funktionsweise der PWM-Kanäle: der Zählerstand des Timers wird fortlaufend mit einen einstellbaren Referenzwert verglichen, und wenn beide Werte übereinstimmen, kann ein Ausgangspin des AVRs automatisch geschaltet werden (und ein Interrupt ausgelöst werden, was allerdings für die PWM-Funktion nicht relevant ist). Dies entspricht dem Verfahren im [[PWM#PWM_per_Software|Beispiel zur Software-PWM]]. Es läuft nun allerdings vollautomatisch im Hintergrund, sodass der Controller nicht damit belastet wird.&lt;br /&gt;
&lt;br /&gt;
==== Die verschiedenen PWM-Modi ====&lt;br /&gt;
Es gibt -je nach AVR und Timer- etliche Betriebsarten, in denen die PWM-Einheit betrieben werden kann. Sie unterscheiden sich vor allem darin, wie schnell und mit welchen Nebeneffekten sich Änderungen des Sollwertes auf das Ausgangssignal auswirken. Für den Anfang sind diese Unterschiede erst einmal nebensächlich, und für eine einfache Motorsteuerung meist auch irrelevant. Daher wird hier zunächst der &amp;quot;Fast PWM Mode&amp;quot; (&amp;quot;Schneller PWM Modus&amp;quot;, weil hier die größte Ausgangsfrequenz möglich ist) beschreiben, welcher der einfachste von allen ist.&lt;br /&gt;
&lt;br /&gt;
Hierbei zählt der Timer immer von Null an aufwärts, bis er den Maximalwert (teilweise einstellbar) erreicht hat. Dann läuft er über und fängt von vorne an. Wie schnell dies geschieht, wird, wie im normalen Modus, über den Prescaler eingestellt.&lt;br /&gt;
Der gewünschte PWM-Ausgangswert wird im &amp;quot;OCRn&amp;quot;-Register abgelegt. Er darf zwischen Null und dem Maximalwert des Timers liegen. Er wird nun mit dem Timer-Wert verglichen. Was dann passiert, regeln die &amp;quot;COM...&amp;quot;-Bits. Sie bestimmen, wie der Ausgang geschaltet wird. Die übliche Konfiguration ist, dass bei Erreichen des Sollwertes die Ausgänge auf high geschaltet werden, und beim Überlauf auf low. Damit ergibt sich ein nichtinvertiertes PWM-Signal. Schließt man (über einem passenden Motortreiber!) einen Motor an, dreht er sich bei einem Sollwert von 0 gar nicht und beim Maximalwert mit voller Geschwindigkeit.&lt;br /&gt;
&lt;br /&gt;
Beispielcode für den Timer1 des Mega16/32 (und vieler anderer AVRs): &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt; //Warteschleife für die Demo-Ausgabe. Für die eigentliche PWM nicht benötigt!  &lt;br /&gt;
&lt;br /&gt;
/*  PWM-Beispiel für Mega16/32 (beiden haben den gleichen Timer)&lt;br /&gt;
	Benutzt wird Timer1 im Fast PWM Mode, 8 Bit Auflösung&lt;br /&gt;
	Die PWM-Signale liegen auf PD5/OC1A und PD4/OC1B&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
// 1. Den Prescaler einstellen, der die Frequenz festlegt&lt;br /&gt;
	TCCR1B |= (1&amp;lt;&amp;lt;CS12); //Prescaler 256&lt;br /&gt;
	&lt;br /&gt;
// 2. Den Timer in den Fast PWM Mode, 8 Bit schalten&lt;br /&gt;
//ACHTUNG: Die WGM-Bits sind auf beide Konfigurationsregister verteiltt!&lt;br /&gt;
	TCCR1A |= (1&amp;lt;&amp;lt;WGM10);&lt;br /&gt;
	TCCR1B |= (1&amp;lt;&amp;lt;WGM12);&lt;br /&gt;
	&lt;br /&gt;
// 3. Compare Output mode einstellen: Pin geht auf high bei Compare match, auf low bei Überlauf. Ergibt nichtinvertierte PWM.	&lt;br /&gt;
	TCCR1A |= (1&amp;lt;&amp;lt;COM1A1) | (1&amp;lt;&amp;lt;COM1B1) ;	&lt;br /&gt;
	&lt;br /&gt;
// In diesen Registern wird der gwünschte PWM-Wert abgelegt. Erlaubter Bereich: 0 bis 255.&lt;br /&gt;
	OCR1A =	0;&lt;br /&gt;
	OCR1B = 0;	&lt;br /&gt;
&lt;br /&gt;
// 4. Zuletzt die Pins als Ausgänge konfigurieren. Erst jetzt liegt das PWM-Signal an den Pins an!	&lt;br /&gt;
	DDRD |= (1&amp;lt;&amp;lt;PD4) | (1&amp;lt;&amp;lt; PD5);&lt;br /&gt;
&lt;br /&gt;
/*Nun ist der PWM-Modus aktiv! Der Ausgangswert kann nun über die Register OCR1A und OCR1B vorgegeben werden. &lt;br /&gt;
Man könnte ihnen per define noch einen Zweitnamen verpassen, zb */&lt;br /&gt;
#define MotorLinks OCR1A&lt;br /&gt;
#define MotorRechts OCR1B&lt;br /&gt;
//Und nun kann man per &lt;br /&gt;
MotorLinks = 127;&lt;br /&gt;
MotorRechts = 127;&lt;br /&gt;
//seinen Roboter mit halber Kraft vorwärts fahren lassen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*PWM-Demo: Die PWM-Werte werden erst bis zum Maximalwert erhöht und dann wieder verringert. &lt;br /&gt;
Ein angeschlossener Motor wird beschleunigen und dann  wieder abbremsen. */&lt;br /&gt;
	uint8_t wert;&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		for (wert=0; wert&amp;lt;255; wert++)&lt;br /&gt;
			{&lt;br /&gt;
				OCR1A =	wert;&lt;br /&gt;
				OCR1B = wert;&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
	&lt;br /&gt;
		for (wert=255; wert&amp;gt;0; wert--)&lt;br /&gt;
			{&lt;br /&gt;
				OCR1A =	wert;&lt;br /&gt;
				OCR1B = wert;&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}	&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind also vier Einstellungen zu treffen:&lt;br /&gt;
# Takt anlegen per Prescaler&lt;br /&gt;
# PWM-Modus wählen&lt;br /&gt;
# Ausgangs-Aktion festlegen&lt;br /&gt;
# Pins als Ausgänge schalten&lt;br /&gt;
&lt;br /&gt;
Diese Schritte müssen bei jedem AVR-PWM-Kanal ausgeführt werden. Die genauen Registernamen und Werte können sich jedoch je nach Timer-Ausführung etwas unterscheiden.&lt;br /&gt;
&lt;br /&gt;
== Registerübersicht ==&lt;br /&gt;
''Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.''&lt;br /&gt;
&lt;br /&gt;
{| {{Blaueschmaltabelle}} width=100%&lt;br /&gt;
 |'''TIMSK'''&lt;br /&gt;
 |-&lt;br /&gt;
 |Mit diesem Register, der von allen Timern verwendet wird, lässt sich die Interruptausführung und Art des jeweiligen Timers bestimmen.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Registertabelle8Bit|OCIE2|TOIE2|TICIE1|OCIE1A|OCIE1B|TOIE1|OCIE0|TOIE0}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
*'''OCIE2 (Timer/Counter2 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE2 (Timer/Counter2 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TICIE1 (Timer/Counter1, Input Capture Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Input Capture Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1A (Timer/Counter1 Output Compare A Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare A Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1B (Timer/Counter1 Output Compare B Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare B Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE1 (Timer/Counter1 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE0 (Timer/Counter0 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Overflow Interrupt aktiviert  (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Atmel]]&lt;br /&gt;
* [[HEX Beispiel-Dateien für AVR]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]&lt;br /&gt;
* [https://mpg.dnsalias.com/~magerlu/rn-wiki/avrtimer_applet Java Applet Timer Berechnung] &lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Elektronik]]&lt;br /&gt;
[[Kategorie:Abkürzung|AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13879</id>
		<title>Timer/Counter (Avr)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13879"/>
				<updated>2008-08-16T21:52:28Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* PWM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Mikrocontroller der AVR-Familie besitzen je nach Typ eine unterschiedliche Anzahl an programmierbaren [[Timer|Timern]]. Bei den aktuellen ATmegas sind das mindestens ein 8-Bit Timer und bei größeren Ausführungen der Serie auch 16-Bit Timer. Die Timer werden immer Timerx benannt, wobei x für die Timernummer steht (also 0, 1, 2, usw.). &lt;br /&gt;
Die Konfigurationsmöglichkeiten sind von Timer zu Timer unterschiedlich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis:''' Die folgenden Code-Beispiele sind in C programmiert und wurden für einen [[ATMega32|ATmega32]] entwickelt. Sie lassen sich also ohne große Änderungen auch auf anderen Mikrocontrollern der AVR-Familie einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Funktionsweise ==&lt;br /&gt;
Timer funktionieren nach dem allgemeinen Prinzip, dass sie eine Ganzzahl (im weiteren als Zähler bezeichnet) je nach Betriebsmodus auf- oder abwärtszählen, d.h. inkrementieren bzw. dekrementieren.&lt;br /&gt;
&lt;br /&gt;
Angenommen, der Timer arbeitet im einfachsten Betriebsmodus, dem normalen Modus (siehe [[Timer/Counter (Avr)#Normaler Modus (Normal Mode)|Normaler Modus (Normal Mode)]]). Die Zählrichtung des Timers ist aufsteigend gerichtet. Je nach Auflösung, also 8-Bit oder 16-Bit, erreicht der Zähler irgendwann einen bestimmten Zustand. Möglich wäre, dass er überläuft, wenn z.B. bei einem 8-Bit Timer der Wert 255 inkrementiert wird (siehe Grafik).&lt;br /&gt;
&lt;br /&gt;
[[Bild:AbstrakterZaehlvorgang.png]]&lt;br /&gt;
&lt;br /&gt;
== Der Prescaler ==&lt;br /&gt;
Der Prescaler (eng. = Vorteiler) kann dazu genutzt werden, den Takt, der den Timern zugeführt wird, zu verkleinern. U.a. kann man damit die Timer so konfigurieren, damit diese in den unterschiedlichsten Frequenzen takten. Hier eine Grafik die den Prescaler veranschaulicht:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Prescaler.png]]&lt;br /&gt;
&lt;br /&gt;
Das obere Diagramm zeigt den Betrieb ohne Prescaler, das untere mit Prescaler. Die gestrichelte Linie zeigt, wann ein Interrupt eintritt.&lt;br /&gt;
&lt;br /&gt;
Im Teil [[Timer/Counter (Avr)#Die Betriebsmodi|Die Betriebsmodi]] wird weiter auf die praktische Verwendung des Prescalers eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Die Betriebsmodi ==&lt;br /&gt;
Die AVR-Timer können in unterschiedlichen Betriebsmodi betrieben werden. Diese sind:&lt;br /&gt;
* Normaler Modus&lt;br /&gt;
* CTC Modus&lt;br /&gt;
* PWM&lt;br /&gt;
&lt;br /&gt;
=== Normaler Modus (Normal Mode) ===&lt;br /&gt;
Der einfachste Betriebsmodus ist der normale Modus. Er funktioniert wie im Abschnitt  &amp;quot;[[Timer/Counter (Avr)#Allgemeine Funktionsweise|Allgemeine Funktionsweise]]&amp;quot; beschrieben. Die Zählrichtung des Timers ist immer aufsteigend, und irgendwann kommt es zu dem Interrupt Timer-Overflow (welcher in einer passend ISR aufgefangen werden kann). Im einfachsten Fall kann man diesen Modus in folgendem Diagramm darstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1.png]]&lt;br /&gt;
&lt;br /&gt;
Der Zähler des Timers (im Diagramm oben, die aufsteigende und dann wieder zurückgesetzte Linie) ist in dem Register TCNTx gespeichert, wobei x für eine Zahl steht. Soll z.B. auf den Timer0 (siehe Datenblatt des jeweiligen Controllers) des Controllers zugegriffen werden, so ist an TCNT eine 0 anzuhängen, also TCNT0.&lt;br /&gt;
Wie lange es braucht, bis der Zähler einen Overflow auslöst, ist von der Taktfrequenz des Controllers, dem eingestellten Prescaler-Wert und von der Timerauflösung abhängig. Nun wäre es ja sehr unpraktisch, wenn wir den Zähler nicht anpassen könnten. Denn sonst müssten wir unsere Software die den Timer benutzt evtl. anpassen und viel rechnen um z.B. für 1000 ms zu schlafen. Deswegen kann auf den Zähler zugreifen und ihn vorladen bevor dieser wieder vom eigentlichen Timer hochgezählt wird. Dies veranschaulicht folgendes Diagramm:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1_Vorladen.png]]&lt;br /&gt;
&lt;br /&gt;
Dadurch kann man den Timer beeinflussen, und beeinflussen wie lange es dauert, bis ein Overflow auftritt. Um zu berechnen, welchen Wert wir vorladen müssen, kann man auch ein Java-Applet nutzen, siehe unter [[Timer/Counter (Avr)#Weblinks|Weblinks Java Applet]].&lt;br /&gt;
&lt;br /&gt;
Natürlich kann man das auch &amp;quot;von Hand&amp;quot; rechnen. Die Berechnung des Preloader- sowie Prescalerwerts bei Verwendung der Overflow-Interrupts, eines Prescalers von 64 (nicht alle Prescaler können verwendet werden) und eines Quarzes mit der Frequenz von 8 MHz sieht folgendermaßen aus (gesuchte Frequenz beträgt 1000 Hz unter der Verwendung des Timer0 eines ATmega32):&lt;br /&gt;
# &amp;lt;math&amp;gt;Prescale = Frequenz * 1000000 [Hz] = 8000000&amp;lt;/math&amp;gt;&lt;br /&gt;
# Wir definieren den maximalen Zählerwert. Dieser ist bei einem 8-Bit Timer 256, bei einem 16-Bit Timer 65536. In unserem Fall ist der maximale Zählerwert 256, weil Timer0 verwendet wird.&lt;br /&gt;
# Nun wird die Variable ''Prescale'' (s.o.) durch den verwendeten Prescaler (64) geteilt (&amp;lt;math&amp;gt;8000000 Hz / 64 = 125000&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Als nächstes wird der im dritten Punkt errechnete Wert durch die gesuchte Frequenz geteilt &amp;lt;math&amp;gt;=125000 / 1000Hz = 125&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird mathematisch überprüft, ob der errechnete Wert aus dem vierten Punkt kleiner als der maximale Zählerwert ist. Trifft dies zu, so subtrahiert man den errechneten Wert vom maximalen Zählerwert (&amp;lt;math&amp;gt;= 256 - 125 = 131&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Damit haben wir den Wert errechnet, der bei jedem Interrupt, den der Timer0 auslöst, in TCNTx (in diesem Fall TCNT0) nachgeladen werden muss, damit die Interrupts in dem gewünschten Zeitabstand von einer Millisekunde ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
Allerdings bleibt zu bemerken, dass bei der Verwendung einer &amp;quot;ungeraden&amp;quot; Quarzfrequenz (z.B. 7,3728 MHz) der Timer mit einer bestimmten Ungenauigkeit arbeitet. Würden wir z.B. den Quarz oben mit einem Quarz mit 7,3728 MHz austauschen, so wäre die Fehlerrate 0,17%. Diese Ungeauigkeit varriert von verwendetem Prescaler zu Prescaler. D.h. wenn wir einen Prescaler von 1024 (und einer Quarzfrequenz von 8 MHz) verwendet hätten, so hätten wir eine inakzeptable Ungeauigkeit von 11,61%. Deswegen sollte sie eines der genannten Programme unter [[Avr#Weblinks]] verwenden, denn diese zeigen nur die bestmögliche Konfiguration an.&lt;br /&gt;
&lt;br /&gt;
Die Fehlerrate kann natürlich auch ausgerechnet werden. Hier die Rechenschritte (sie sind erweiternd zu der oberen Berechnung):&lt;br /&gt;
# Als erstes wird mathematisch überprüft, ob der Preloaderwert (siehe fünften Schritt oben) größer als 1 ist.&lt;br /&gt;
# Trifft dies zu, so wird als nächstes die resultierende Frequenz errechnet. Die geschieht folgendermaßen: Der errechnete Preloaderwert aus der Rechnung oben wird vom maximalen Zählerwert subtrahiert, anschließend mit dem Prescaler multipliziert und dann das Ganze durch die Variable Prescale geteilt &lt;br /&gt;
&amp;lt;math&amp;gt;(256 - 131) \cdot 64 / 8\,000\,000 \mathrm{Hz} \cdot 1\,000\,000 = 1000&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird die gesuchte Frequenz vom errechneten Wert aus dem dritten Punkt subtrahiert und dann wiederum durch diese geteilt &amp;lt;math&amp;gt;(1000-1000) / 1000 = 0&amp;lt;/math&amp;gt;. Damit läuft dieser Timer genau mit einer Fehlerrate von 0 %.&lt;br /&gt;
&lt;br /&gt;
Betreibt man den Timer im Overflow-Modus, so muss man, wie bereits erwähnt, nach/bei jedem Overflow-Interrupt den Timer nachladen. Der Interrupt heißt in diesem Fall SIG_OVERFLOWx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine&lt;br /&gt;
Frequenz von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und&lt;br /&gt;
einem Preloader von  183 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_SIG_OVERFLOW2)&lt;br /&gt;
{&lt;br /&gt;
	countTimer2++;&lt;br /&gt;
	TCNT2 = 183;		// Nachladen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22);		// Prescaler von 1&lt;br /&gt;
TCNT2  = 183;			// Vorladen&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;TOIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep (uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Allerdings wird auf diese leicht veraltete Technik nun nicht weiter eingegangen. Der Artikel wendet sich nun dem neueren &amp;quot;Compare Output&amp;quot;-Betriebsmodus zu.&lt;br /&gt;
&lt;br /&gt;
Beim &amp;quot;Compare Output&amp;quot;-Betriebsmodus wird genauso ein Zähler hochgezählt. Allerdings wird der Zählerwert nach jeder Inkrementierung mit einem vom Benutzer festgelegten Wert verglichen. Entspricht der Zählerwert dem gespeicherten Wert, so kommt es zu einem Interrupt. Dieser Wert wird in das Register OCRx (x steht wieder für die Timernummer) gespeichert. Je nach Auflösung des Timers ist dieses Register 8-Bit oder 16-Bit breit. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Siehe CTC Modus unten. Dieser wird benötigt um den Timer entsprechend im &amp;quot;Compare Output&amp;quot;-Betriebsmodus vernünftig zu betreiben.&lt;br /&gt;
&lt;br /&gt;
Hier ein typisches Diagramm dieses Betriebsmodus (Hinweis: Das Diagramm wurde unter Verwendung des CTC Modus erstellt. Für Begriffserklärung siehe CTC Modus):&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
Das Ausrechnen des Werts, der in OCRx geschrieben werden muss, damit Frequenz x entsteht, ist nicht sonderlich schwer. Man geht wie bei der Berechnung des Werts für den Overflow-Modus vor (s.o.) nur daß man das resultierende Ergebnis vom maximalen Zählerwert (bei 8-Bit Auflösung ist dieser 256, bei 16-Bit Auflösung 65536) subtrahiert. Das Ergebnis wird dann einmalig in das Register OCRx geschrieben. Mann muss also nicht wie beim Overflow-Modus den Timer nach jedem Interrupt nachladen. Der enstehende Interrupt heißt in diesem Fall SIG_OUTPUT_COMPAREx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Wiederum zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine Frequenz&lt;br /&gt;
von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und einem OCR2-Wert&lt;br /&gt;
von 73 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE2)&lt;br /&gt;
{&lt;br /&gt;
  countTimer2++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22) | (1&amp;lt;&amp;lt;WGM21);	// Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)&lt;br /&gt;
OCR2  = 73;			// Vergleichswert&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;OCIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep(uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CTC Modus (Clear Timer on Compare Match mode) ===&lt;br /&gt;
Der CTC Modus ist eine Erweiterung des &amp;quot;Compare Output&amp;quot;-Betriebsmodus. Der CTC Modus wird z.B. für das obere Beispielprogramm benötigt. Wird der Timer nämlich im normalen Betriebsmodus betrieben, so ist seine Zählergrenze je nach Auflösung 255 oder entsprechend für die 16-Bit Timer. Erst wenn diese Grenze erreicht wurde, wird der Timer zurückgesetzt (also auf 0). Durch den CTC Modus wird der Timer augenblicklich automatisch zurückgesetzt nachdem der Vergleichswert erreicht ist. Man kann also die maximalen Zählergrenze selber definieren.&lt;br /&gt;
Dieses Diagramm veranschaulicht den CTC Modus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
=== PWM ===&lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Eine häufige Aufgabe für Mikrocontroller ist die Erzeugung von [[PWM]]-Signalen, zum Beispiel für Motorsteuerungen. Daher sind in den meisten [[AVR|AVRs]] PWM-Einheiten als Hardware vorhanden. Sie sind direkt mit den Timern verbunden und nutzen diese als Taktquelle. Die Hardware-PWM-Einheiten haben den Vorteil, sehr wenig Rechenzeit in Anspruch zu nehmen. Man muss nur die PWM aktivieren und bei Änderungen den gewünschten Wert in ein Register schreiben. Der Rest läuft automatisch und unabhängig vom restlichen Programm, ohne den AVr ständig zu beschäftigen wie bei einer PWM-Lösung in Software. Allerdings stehen meist nur zwei bis drei solcher PWM-Kanäle zur Verfügung, die außerdem an bestimmte Pins gebunden sind. Für die meisten Roboter mit zwei Antriebsmotoren reicht dies aber für gewöhnlich aus. &lt;br /&gt;
&lt;br /&gt;
==== nutzbare Pins am AVR ====&lt;br /&gt;
Die Hardware-PWm-Funktion steht nur an bestimmten Pins zur Verfügung. In der Pinbelegungsübersicht im Datenblatt erkennt man sie daran, dass als Sonderfunktion in Klammern &amp;quot;OC...&amp;quot; angegeben ist. Beim Mega32 sind dies zb. OC0 an PB0, OC1A an PD5, OC1B an PD4 und OC2 an PD7. Der Mega32 hat also insgesamt vier Hardware-PWM-Kanäle. Die Zahl hinter dem &amp;quot;OC&amp;quot; gibt an, zu welchem der Timer dieser PWM-Kanal gehört. Wenn noch ein Buchstabe dahinter kommt, dann gehören mehrere PWMs zu diesem Timer. Beim Mega32 sind also OC1A und OC1B demselben Timer, nämlich Timer1, zugeordnet.&lt;br /&gt;
&lt;br /&gt;
'''Zu beachten ist, dass die für die PWM benutzten Pins zuvor explizit als Ausgang konfiguriert werden müssen! Ansonsten gelangt das PWM-Signal nicht nach draußen!'''&lt;br /&gt;
&lt;br /&gt;
==== Funktionsprinzip ====&lt;br /&gt;
Das &amp;quot;OC&amp;quot; in den Pinbezeichnungen steht für &amp;quot;Output Compare Unit&amp;quot;, also frei übersetzt Ausgangs-Vergleicher-Einheit. Dies beschreibt die Funktionsweise der PWM-Kanäle: der Zählerstand des Timers wird fortlaufend mit einen einstellbaren Referenzwert verglichen, und wenn beide Werte übereinstimmen, kann ein Ausgangspin des AVRs automatisch geschaltet werden (und ein Interrupt ausgelöst werden, was allerdings für die PWM-Funktion nicht relevant ist). Dies entspricht den Verfahren im [[PWM#PWM_per_Software|Beispiel zur Software-PWM]]. Es läuft nun allerdings vollautomatisch im Hintergrund, sodass der Controller nicht damit belastet wird.&lt;br /&gt;
&lt;br /&gt;
==== Die verschiedenen PWM-Modi ====&lt;br /&gt;
Es gibt -je nach AVR und Timer- etliche Betriebsarten, in denen die PWM-Einheit betrieben werden kann. Sie unterscheiden sich vor allem darin, wie schnell und mit welchen Nebeneffekten sich Änderungen des Sollwertes auf das Ausgangssignal auswirken. Für den Anfang sind diese Unterschiede erst einmal nebensächlich, und für eine einfache Motorsteuerung meist auch irrelevant. Daher wird hier zunächst der &amp;quot;Fast PWM Mode&amp;quot; (&amp;quot;Schneller PWM Modus&amp;quot;, weil hier die größte Ausgangsfrequenz möglich ist) beschreiben, welcher der einfachste von allen ist.&lt;br /&gt;
&lt;br /&gt;
Hierbei zählt der Timer immer von Null an aufwärts, bis er den Maximalwert (teilweise einstellbar) erreicht hat. Dann läuft er über und fängt von vorne an. Wie schnell dies geschieht, wird, wie im normalen Modus, über den Prescaler eingestellt.&lt;br /&gt;
Der gewünschte PWM-Ausgangswert wird im &amp;quot;OCRn&amp;quot;-Register abgelegt. Er darf zwischen Null und dem Maximalwert des Timers liegen. Er wird nun mit dem Timer-Wert verglichen. Was dann passiert, reglen die &amp;quot;COM...&amp;quot;-Bits. Sie bestimmen, wie der Ausgang geschaltet wird. Die übliche Konfiguration ist, dass bei erreichen des Sollwertes die Ausgänge auf high geschaltet werden, und beim Überlauf auf low. Damit ergibt sich ein nichtinvertiertes Signal. Schließt man (über einem passenden Motortreiber!) einen Motor an, dreht er sich bei einem Sollwert von 0 gar nicht und beim Maximalwert mit voller Geschwindigkeit.&lt;br /&gt;
&lt;br /&gt;
Beispielcode für den timer1 des Mega16/32 (und vieler anderer AVRs): &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt; //Warteschleife für die Demo-Ausgabe. Für die eigentliche PWM nicht benötigt!  &lt;br /&gt;
&lt;br /&gt;
/*  PWM-Beispiel für Mega16/32 (beiden haben den gleichen Timer)&lt;br /&gt;
	Benutzt wird Timer1 im Fast PWM Mode, 8 Bit Auflösung&lt;br /&gt;
	Die PWM-Signale liegen auf PD5/OC1A und PD4/OC1B&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
//Den Prescaler einstellen, der die Frequenz festlegt&lt;br /&gt;
	TCCR1B |= (1&amp;lt;&amp;lt;CS12); //Prescaler 256&lt;br /&gt;
	&lt;br /&gt;
//Den Timer in den Fast PWM Mode, 8 Bit schalten&lt;br /&gt;
//ACHTUNG: Die WGM-Bits sind auf beide Konfigurationsregister verteiltt!&lt;br /&gt;
	TCCR1A |= (1&amp;lt;&amp;lt;WGM10);&lt;br /&gt;
	TCCR1B |= (1&amp;lt;&amp;lt;WGM12);&lt;br /&gt;
	&lt;br /&gt;
//Compare Output mode einstellen: Pin geht auf high bei Compare match, auf low bei Überlauf. Ergibt nichtinvertierte PWM.	&lt;br /&gt;
	TCCR1A |= (1&amp;lt;&amp;lt;COM1A1) | (1&amp;lt;&amp;lt;COM1B1) ;	&lt;br /&gt;
	&lt;br /&gt;
// In diesen Registern wird der gwünschte PWM-Wert abgelegt. Erlaubter Bereich: 0 bis 255.&lt;br /&gt;
	OCR1A =	0;&lt;br /&gt;
	OCR1B = 0;	&lt;br /&gt;
&lt;br /&gt;
//Zuletzt die Pins als Ausgänge konfigurieren. Erst jetzt liegt das PWM-Signal an den Pins an!	&lt;br /&gt;
	DDRD |= (1&amp;lt;&amp;lt;PD4) | (1&amp;lt;&amp;lt; PD5);&lt;br /&gt;
&lt;br /&gt;
/*Nun ist der PWM-Modus aktiv! Der Ausgangswert kann nun über die Register OCR1A und OCR1B vorgegeben werden. &lt;br /&gt;
Man könnte ihnen per define noch einen Zweitnamen verpassen, zb */&lt;br /&gt;
#define MotorLinks OCR1A&lt;br /&gt;
#define MotorRechts OCR1B&lt;br /&gt;
//Und nun kann man per &lt;br /&gt;
MotorLinks = 127;&lt;br /&gt;
MotorRechts = 127;&lt;br /&gt;
//seinen Roboter mit halber Kraft vorwärts fahren lassen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*PWM-Demo: Die PWM-Werte werden erst bis zum Maximalwert erhöht und dann wieder verringert. &lt;br /&gt;
Ein angeschlossener Motor wird beschleunigen und dann  wieder abbremsen. */&lt;br /&gt;
	uint8_t wert;&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		for (wert=0; wert&amp;lt;255; wert++)&lt;br /&gt;
			{&lt;br /&gt;
				OCR1A =	wert;&lt;br /&gt;
				OCR1B = wert;&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
	&lt;br /&gt;
		for (wert=255; wert&amp;gt;0; wert--)&lt;br /&gt;
			{&lt;br /&gt;
				OCR1A =	wert;&lt;br /&gt;
				OCR1B = wert;&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}	&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerübersicht ==&lt;br /&gt;
''Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.''&lt;br /&gt;
&lt;br /&gt;
{| {{Blaueschmaltabelle}} width=100%&lt;br /&gt;
 |'''TIMSK'''&lt;br /&gt;
 |-&lt;br /&gt;
 |Mit diesem Register, der von allen Timern verwendet wird, lässt sich die Interruptausführung und Art des jeweiligen Timers bestimmen.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Registertabelle8Bit|OCIE2|TOIE2|TICIE1|OCIE1A|OCIE1B|TOIE1|OCIE0|TOIE0}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
*'''OCIE2 (Timer/Counter2 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE2 (Timer/Counter2 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TICIE1 (Timer/Counter1, Input Capture Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Input Capture Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1A (Timer/Counter1 Output Compare A Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare A Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1B (Timer/Counter1 Output Compare B Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare B Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE1 (Timer/Counter1 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE0 (Timer/Counter0 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Overflow Interrupt aktiviert  (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Atmel]]&lt;br /&gt;
* [[HEX Beispiel-Dateien für AVR]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]&lt;br /&gt;
* [https://mpg.dnsalias.com/~magerlu/rn-wiki/avrtimer_applet Java Applet Timer Berechnung] &lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Elektronik]]&lt;br /&gt;
[[Kategorie:Abkürzung|AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13878</id>
		<title>Timer/Counter (Avr)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13878"/>
				<updated>2008-08-16T20:28:30Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* PWM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Mikrocontroller der AVR-Familie besitzen je nach Typ eine unterschiedliche Anzahl an programmierbaren [[Timer|Timern]]. Bei den aktuellen ATmegas sind das mindestens ein 8-Bit Timer und bei größeren Ausführungen der Serie auch 16-Bit Timer. Die Timer werden immer Timerx benannt, wobei x für die Timernummer steht (also 0, 1, 2, usw.). &lt;br /&gt;
Die Konfigurationsmöglichkeiten sind von Timer zu Timer unterschiedlich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis:''' Die folgenden Code-Beispiele sind in C programmiert und wurden für einen [[ATMega32|ATmega32]] entwickelt. Sie lassen sich also ohne große Änderungen auch auf anderen Mikrocontrollern der AVR-Familie einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Funktionsweise ==&lt;br /&gt;
Timer funktionieren nach dem allgemeinen Prinzip, dass sie eine Ganzzahl (im weiteren als Zähler bezeichnet) je nach Betriebsmodus auf- oder abwärtszählen, d.h. inkrementieren bzw. dekrementieren.&lt;br /&gt;
&lt;br /&gt;
Angenommen, der Timer arbeitet im einfachsten Betriebsmodus, dem normalen Modus (siehe [[Timer/Counter (Avr)#Normaler Modus (Normal Mode)|Normaler Modus (Normal Mode)]]). Die Zählrichtung des Timers ist aufsteigend gerichtet. Je nach Auflösung, also 8-Bit oder 16-Bit, erreicht der Zähler irgendwann einen bestimmten Zustand. Möglich wäre, dass er überläuft, wenn z.B. bei einem 8-Bit Timer der Wert 255 inkrementiert wird (siehe Grafik).&lt;br /&gt;
&lt;br /&gt;
[[Bild:AbstrakterZaehlvorgang.png]]&lt;br /&gt;
&lt;br /&gt;
== Der Prescaler ==&lt;br /&gt;
Der Prescaler (eng. = Vorteiler) kann dazu genutzt werden, den Takt, der den Timern zugeführt wird, zu verkleinern. U.a. kann man damit die Timer so konfigurieren, damit diese in den unterschiedlichsten Frequenzen takten. Hier eine Grafik die den Prescaler veranschaulicht:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Prescaler.png]]&lt;br /&gt;
&lt;br /&gt;
Das obere Diagramm zeigt den Betrieb ohne Prescaler, das untere mit Prescaler. Die gestrichelte Linie zeigt, wann ein Interrupt eintritt.&lt;br /&gt;
&lt;br /&gt;
Im Teil [[Timer/Counter (Avr)#Die Betriebsmodi|Die Betriebsmodi]] wird weiter auf die praktische Verwendung des Prescalers eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Die Betriebsmodi ==&lt;br /&gt;
Die AVR-Timer können in unterschiedlichen Betriebsmodi betrieben werden. Diese sind:&lt;br /&gt;
* Normaler Modus&lt;br /&gt;
* CTC Modus&lt;br /&gt;
* PWM&lt;br /&gt;
&lt;br /&gt;
=== Normaler Modus (Normal Mode) ===&lt;br /&gt;
Der einfachste Betriebsmodus ist der normale Modus. Er funktioniert wie im Abschnitt  &amp;quot;[[Timer/Counter (Avr)#Allgemeine Funktionsweise|Allgemeine Funktionsweise]]&amp;quot; beschrieben. Die Zählrichtung des Timers ist immer aufsteigend, und irgendwann kommt es zu dem Interrupt Timer-Overflow (welcher in einer passend ISR aufgefangen werden kann). Im einfachsten Fall kann man diesen Modus in folgendem Diagramm darstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1.png]]&lt;br /&gt;
&lt;br /&gt;
Der Zähler des Timers (im Diagramm oben, die aufsteigende und dann wieder zurückgesetzte Linie) ist in dem Register TCNTx gespeichert, wobei x für eine Zahl steht. Soll z.B. auf den Timer0 (siehe Datenblatt des jeweiligen Controllers) des Controllers zugegriffen werden, so ist an TCNT eine 0 anzuhängen, also TCNT0.&lt;br /&gt;
Wie lange es braucht, bis der Zähler einen Overflow auslöst, ist von der Taktfrequenz des Controllers, dem eingestellten Prescaler-Wert und von der Timerauflösung abhängig. Nun wäre es ja sehr unpraktisch, wenn wir den Zähler nicht anpassen könnten. Denn sonst müssten wir unsere Software die den Timer benutzt evtl. anpassen und viel rechnen um z.B. für 1000 ms zu schlafen. Deswegen kann auf den Zähler zugreifen und ihn vorladen bevor dieser wieder vom eigentlichen Timer hochgezählt wird. Dies veranschaulicht folgendes Diagramm:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1_Vorladen.png]]&lt;br /&gt;
&lt;br /&gt;
Dadurch kann man den Timer beeinflussen, und beeinflussen wie lange es dauert, bis ein Overflow auftritt. Um zu berechnen, welchen Wert wir vorladen müssen, kann man auch ein Java-Applet nutzen, siehe unter [[Timer/Counter (Avr)#Weblinks|Weblinks Java Applet]].&lt;br /&gt;
&lt;br /&gt;
Natürlich kann man das auch &amp;quot;von Hand&amp;quot; rechnen. Die Berechnung des Preloader- sowie Prescalerwerts bei Verwendung der Overflow-Interrupts, eines Prescalers von 64 (nicht alle Prescaler können verwendet werden) und eines Quarzes mit der Frequenz von 8 MHz sieht folgendermaßen aus (gesuchte Frequenz beträgt 1000 Hz unter der Verwendung des Timer0 eines ATmega32):&lt;br /&gt;
# &amp;lt;math&amp;gt;Prescale = Frequenz * 1000000 [Hz] = 8000000&amp;lt;/math&amp;gt;&lt;br /&gt;
# Wir definieren den maximalen Zählerwert. Dieser ist bei einem 8-Bit Timer 256, bei einem 16-Bit Timer 65536. In unserem Fall ist der maximale Zählerwert 256, weil Timer0 verwendet wird.&lt;br /&gt;
# Nun wird die Variable ''Prescale'' (s.o.) durch den verwendeten Prescaler (64) geteilt (&amp;lt;math&amp;gt;8000000 Hz / 64 = 125000&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Als nächstes wird der im dritten Punkt errechnete Wert durch die gesuchte Frequenz geteilt &amp;lt;math&amp;gt;=125000 / 1000Hz = 125&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird mathematisch überprüft, ob der errechnete Wert aus dem vierten Punkt kleiner als der maximale Zählerwert ist. Trifft dies zu, so subtrahiert man den errechneten Wert vom maximalen Zählerwert (&amp;lt;math&amp;gt;= 256 - 125 = 131&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Damit haben wir den Wert errechnet, der bei jedem Interrupt, den der Timer0 auslöst, in TCNTx (in diesem Fall TCNT0) nachgeladen werden muss, damit die Interrupts in dem gewünschten Zeitabstand von einer Millisekunde ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
Allerdings bleibt zu bemerken, dass bei der Verwendung einer &amp;quot;ungeraden&amp;quot; Quarzfrequenz (z.B. 7,3728 MHz) der Timer mit einer bestimmten Ungenauigkeit arbeitet. Würden wir z.B. den Quarz oben mit einem Quarz mit 7,3728 MHz austauschen, so wäre die Fehlerrate 0,17%. Diese Ungeauigkeit varriert von verwendetem Prescaler zu Prescaler. D.h. wenn wir einen Prescaler von 1024 (und einer Quarzfrequenz von 8 MHz) verwendet hätten, so hätten wir eine inakzeptable Ungeauigkeit von 11,61%. Deswegen sollte sie eines der genannten Programme unter [[Avr#Weblinks]] verwenden, denn diese zeigen nur die bestmögliche Konfiguration an.&lt;br /&gt;
&lt;br /&gt;
Die Fehlerrate kann natürlich auch ausgerechnet werden. Hier die Rechenschritte (sie sind erweiternd zu der oberen Berechnung):&lt;br /&gt;
# Als erstes wird mathematisch überprüft, ob der Preloaderwert (siehe fünften Schritt oben) größer als 1 ist.&lt;br /&gt;
# Trifft dies zu, so wird als nächstes die resultierende Frequenz errechnet. Die geschieht folgendermaßen: Der errechnete Preloaderwert aus der Rechnung oben wird vom maximalen Zählerwert subtrahiert, anschließend mit dem Prescaler multipliziert und dann das Ganze durch die Variable Prescale geteilt &lt;br /&gt;
&amp;lt;math&amp;gt;(256 - 131) \cdot 64 / 8\,000\,000 \mathrm{Hz} \cdot 1\,000\,000 = 1000&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird die gesuchte Frequenz vom errechneten Wert aus dem dritten Punkt subtrahiert und dann wiederum durch diese geteilt &amp;lt;math&amp;gt;(1000-1000) / 1000 = 0&amp;lt;/math&amp;gt;. Damit läuft dieser Timer genau mit einer Fehlerrate von 0 %.&lt;br /&gt;
&lt;br /&gt;
Betreibt man den Timer im Overflow-Modus, so muss man, wie bereits erwähnt, nach/bei jedem Overflow-Interrupt den Timer nachladen. Der Interrupt heißt in diesem Fall SIG_OVERFLOWx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine&lt;br /&gt;
Frequenz von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und&lt;br /&gt;
einem Preloader von  183 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_SIG_OVERFLOW2)&lt;br /&gt;
{&lt;br /&gt;
	countTimer2++;&lt;br /&gt;
	TCNT2 = 183;		// Nachladen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22);		// Prescaler von 1&lt;br /&gt;
TCNT2  = 183;			// Vorladen&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;TOIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep (uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Allerdings wird auf diese leicht veraltete Technik nun nicht weiter eingegangen. Der Artikel wendet sich nun dem neueren &amp;quot;Compare Output&amp;quot;-Betriebsmodus zu.&lt;br /&gt;
&lt;br /&gt;
Beim &amp;quot;Compare Output&amp;quot;-Betriebsmodus wird genauso ein Zähler hochgezählt. Allerdings wird der Zählerwert nach jeder Inkrementierung mit einem vom Benutzer festgelegten Wert verglichen. Entspricht der Zählerwert dem gespeicherten Wert, so kommt es zu einem Interrupt. Dieser Wert wird in das Register OCRx (x steht wieder für die Timernummer) gespeichert. Je nach Auflösung des Timers ist dieses Register 8-Bit oder 16-Bit breit. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Siehe CTC Modus unten. Dieser wird benötigt um den Timer entsprechend im &amp;quot;Compare Output&amp;quot;-Betriebsmodus vernünftig zu betreiben.&lt;br /&gt;
&lt;br /&gt;
Hier ein typisches Diagramm dieses Betriebsmodus (Hinweis: Das Diagramm wurde unter Verwendung des CTC Modus erstellt. Für Begriffserklärung siehe CTC Modus):&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
Das Ausrechnen des Werts, der in OCRx geschrieben werden muss, damit Frequenz x entsteht, ist nicht sonderlich schwer. Man geht wie bei der Berechnung des Werts für den Overflow-Modus vor (s.o.) nur daß man das resultierende Ergebnis vom maximalen Zählerwert (bei 8-Bit Auflösung ist dieser 256, bei 16-Bit Auflösung 65536) subtrahiert. Das Ergebnis wird dann einmalig in das Register OCRx geschrieben. Mann muss also nicht wie beim Overflow-Modus den Timer nach jedem Interrupt nachladen. Der enstehende Interrupt heißt in diesem Fall SIG_OUTPUT_COMPAREx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Wiederum zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine Frequenz&lt;br /&gt;
von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und einem OCR2-Wert&lt;br /&gt;
von 73 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE2)&lt;br /&gt;
{&lt;br /&gt;
  countTimer2++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22) | (1&amp;lt;&amp;lt;WGM21);	// Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)&lt;br /&gt;
OCR2  = 73;			// Vergleichswert&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;OCIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep(uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CTC Modus (Clear Timer on Compare Match mode) ===&lt;br /&gt;
Der CTC Modus ist eine Erweiterung des &amp;quot;Compare Output&amp;quot;-Betriebsmodus. Der CTC Modus wird z.B. für das obere Beispielprogramm benötigt. Wird der Timer nämlich im normalen Betriebsmodus betrieben, so ist seine Zählergrenze je nach Auflösung 255 oder entsprechend für die 16-Bit Timer. Erst wenn diese Grenze erreicht wurde, wird der Timer zurückgesetzt (also auf 0). Durch den CTC Modus wird der Timer augenblicklich automatisch zurückgesetzt nachdem der Vergleichswert erreicht ist. Man kann also die maximalen Zählergrenze selber definieren.&lt;br /&gt;
Dieses Diagramm veranschaulicht den CTC Modus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
=== PWM ===&lt;br /&gt;
&lt;br /&gt;
{{Baustelle|uwegw}}&lt;br /&gt;
&lt;br /&gt;
Eine häufige Aufgabe für Mikrocontroller ist die Erzeugung von [[PWM]]-Signalen, zum Beispiel für Motorsteuerungen. Daher sind in den meisten [[AVR|AVRs]] PWM-Einheiten als Hardware vorhanden. Sie sind direkt mit den Timern verbunden und nutzen diese als Taktquelle. Die Hardware-PWM-Einheiten haben den Vorteil, sehr wenig Rechenzeit in Anspruch zu nehmen. Man muss nur die PWM aktivieren und bei Änderungen den gewünschten Wert in ein Register schreiben. Der Rest läuft automatisch und unabhängig vom restlichen Programm, ohne den AVr ständig zu beschäftigen wie bei einer PWM-Lösung in Software. Allerdings stehen meist nur zwei bis drei solcher PWM-Kanäle zur Verfügung, die außerdem an bestimmte Pins gebunden sind. Für die meisten Roboter mit zwei Antriebsmotoren reicht dies aber für gewöhnlich aus. &lt;br /&gt;
&lt;br /&gt;
==== nutzbare Pins am AVR ====&lt;br /&gt;
Die Hardware-PWm-Funktion steht nur an bestimmten Pins zur Verfügung. In der Pinbelegungsübersicht im Datenblatt erkennt man sie daran, dass als Sonderfunktion in Klammern &amp;quot;OC...&amp;quot; angegeben ist. Beim Mega32 sind dies zb. OC0 an PB0, OC1A an PD5, OC1B an PD4 und OC2 an PD7. Der Mega32 hat also insgesamt vier Hardware-PWM-Kanäle. Die Zahl hinter dem &amp;quot;OC&amp;quot; gibt an, zu welchem der Timer dieser PWM-Kanal gehört. Wenn noch ein Buchstabe dahinter kommt, dann gehören mehrere PWMs zu diesem Timer. Beim Mega32 sind also OC1A und OC1B demselben Timer, nämlich Timer1, zugeordnet.&lt;br /&gt;
&lt;br /&gt;
'''Zu beachten ist, dass die für die PWM benutzten Pins zuvor explizit als Ausgang konfiguriert werden müssen! Ansonsten gelangt das PWM-Signal nicht nach draußen!'''&lt;br /&gt;
&lt;br /&gt;
==== Funktionsprinzip ====&lt;br /&gt;
Das &amp;quot;OC&amp;quot; in den Pinbezeichnungen steht für &amp;quot;Output Compare Unit&amp;quot;, also frei übersetzt Ausgangs-Vergleicher-Einheit. Dies beschreibt die Funktionsweise der PWM-Kanäle: der Zählerstand des Timers wird fortlaufend mit einen einstellbaren Referenzwert verglichen, und wenn beide Werte übereinstimmen, kann ein Ausgangspin des AVRs automatisch geschaltet werden (und ein Interrupt ausgelöst werden, was allerdings für die PWM-Funktion nicht relevant ist). Dies entspricht den Verfahren im [[PWM#PWM_per_Software|Beispiel zur Software-PWM]]. Es läuft nun allerdings vollautomatisch im Hintergrund, sodass der Controller nicht damit belastet wird.&lt;br /&gt;
&lt;br /&gt;
==== Die verschiedenen PWM-Modi ====&lt;br /&gt;
Es gibt -je nach AVR und Timer- etliche Betriebsarten, in denen die PWM-Einheit betrieben werden kann. Sie unterscheiden sich vor allem darin, wie schnell und mit welchen Nebeneffekten sich Änderungen des Sollwertes auf das Ausgangssignal auswirken. Für den Anfang sind diese Unterschiede erst einmal nebensächlich, und für eine einfache Motorsteuerung meist auch irrelevant. Daher wird hier zunächst der &amp;quot;Fast PWM Mode&amp;quot; (&amp;quot;Schneller PWM Modus&amp;quot;, weil hier die größte Ausgangsfrequenz möglich ist) beschreiben, welcher der einfachste von allen ist.&lt;br /&gt;
&lt;br /&gt;
Hierbei zählt der Timer immer von Null an aufwärts, bis er den Maximalwert (teilweise einstellbar) erreicht hat. Dann läuft er über und fängt von vorne an. Wie schnell dies geschieht, wird, wie im normalen Modus, über den Prescaler eingestellt.&lt;br /&gt;
Der gewünschte PWM-Ausgangswert wird im &amp;quot;OCRn&amp;quot;-Register abgelegt. Er darf zwischen Null und dem Maximalwert des Timers liegen. Er wird nun mit dem Timer-Wert verglichen. Was dann passiert, reglen die &amp;quot;COM...&amp;quot;-Bits. Sie bestimmen, wie der Ausgang geschaltet wird. Die übliche Konfiguration ist, dass bei erreichen des Sollwertes die Ausgänge auf high geschaltet werden, und beim Überlauf auf low. Damit ergibt sich ein nichtinvertiertes Signal. Schließt man (über einem passenden Motortreiber!) einen Motor an, dreht er sich bei einem Sollwert von 0 gar nicht und bei MAX mit voller Geschwindigkeit.&lt;br /&gt;
&lt;br /&gt;
== Registerübersicht ==&lt;br /&gt;
''Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.''&lt;br /&gt;
&lt;br /&gt;
{| {{Blaueschmaltabelle}} width=100%&lt;br /&gt;
 |'''TIMSK'''&lt;br /&gt;
 |-&lt;br /&gt;
 |Mit diesem Register, der von allen Timern verwendet wird, lässt sich die Interruptausführung und Art des jeweiligen Timers bestimmen.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Registertabelle8Bit|OCIE2|TOIE2|TICIE1|OCIE1A|OCIE1B|TOIE1|OCIE0|TOIE0}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
*'''OCIE2 (Timer/Counter2 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE2 (Timer/Counter2 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TICIE1 (Timer/Counter1, Input Capture Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Input Capture Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1A (Timer/Counter1 Output Compare A Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare A Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1B (Timer/Counter1 Output Compare B Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare B Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE1 (Timer/Counter1 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE0 (Timer/Counter0 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Overflow Interrupt aktiviert  (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Atmel]]&lt;br /&gt;
* [[HEX Beispiel-Dateien für AVR]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]&lt;br /&gt;
* [https://mpg.dnsalias.com/~magerlu/rn-wiki/avrtimer_applet Java Applet Timer Berechnung] &lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Elektronik]]&lt;br /&gt;
[[Kategorie:Abkürzung|AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13877</id>
		<title>Timer/Counter (Avr)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13877"/>
				<updated>2008-08-16T19:39:45Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Mikrocontroller der AVR-Familie besitzen je nach Typ eine unterschiedliche Anzahl an programmierbaren [[Timer|Timern]]. Bei den aktuellen ATmegas sind das mindestens ein 8-Bit Timer und bei größeren Ausführungen der Serie auch 16-Bit Timer. Die Timer werden immer Timerx benannt, wobei x für die Timernummer steht (also 0, 1, 2, usw.). &lt;br /&gt;
Die Konfigurationsmöglichkeiten sind von Timer zu Timer unterschiedlich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis:''' Die folgenden Code-Beispiele sind in C programmiert und wurden für einen [[ATMega32|ATmega32]] entwickelt. Sie lassen sich also ohne große Änderungen auch auf anderen Mikrocontrollern der AVR-Familie einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Funktionsweise ==&lt;br /&gt;
Timer funktionieren nach dem allgemeinen Prinzip, dass sie eine Ganzzahl (im weiteren als Zähler bezeichnet) je nach Betriebsmodus auf- oder abwärtszählen, d.h. inkrementieren bzw. dekrementieren.&lt;br /&gt;
&lt;br /&gt;
Angenommen, der Timer arbeitet im einfachsten Betriebsmodus, dem normalen Modus (siehe [[Timer/Counter (Avr)#Normaler Modus (Normal Mode)|Normaler Modus (Normal Mode)]]). Die Zählrichtung des Timers ist aufsteigend gerichtet. Je nach Auflösung, also 8-Bit oder 16-Bit, erreicht der Zähler irgendwann einen bestimmten Zustand. Möglich wäre, dass er überläuft, wenn z.B. bei einem 8-Bit Timer der Wert 255 inkrementiert wird (siehe Grafik).&lt;br /&gt;
&lt;br /&gt;
[[Bild:AbstrakterZaehlvorgang.png]]&lt;br /&gt;
&lt;br /&gt;
== Der Prescaler ==&lt;br /&gt;
Der Prescaler (eng. = Vorteiler) kann dazu genutzt werden, den Takt, der den Timern zugeführt wird, zu verkleinern. U.a. kann man damit die Timer so konfigurieren, damit diese in den unterschiedlichsten Frequenzen takten. Hier eine Grafik die den Prescaler veranschaulicht:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Prescaler.png]]&lt;br /&gt;
&lt;br /&gt;
Das obere Diagramm zeigt den Betrieb ohne Prescaler, das untere mit Prescaler. Die gestrichelte Linie zeigt, wann ein Interrupt eintritt.&lt;br /&gt;
&lt;br /&gt;
Im Teil [[Timer/Counter (Avr)#Die Betriebsmodi|Die Betriebsmodi]] wird weiter auf die praktische Verwendung des Prescalers eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Die Betriebsmodi ==&lt;br /&gt;
Die AVR-Timer können in unterschiedlichen Betriebsmodi betrieben werden. Diese sind:&lt;br /&gt;
* Normaler Modus&lt;br /&gt;
* CTC Modus&lt;br /&gt;
* PWM&lt;br /&gt;
&lt;br /&gt;
=== Normaler Modus (Normal Mode) ===&lt;br /&gt;
Der einfachste Betriebsmodus ist der normale Modus. Er funktioniert wie im Abschnitt  &amp;quot;[[Timer/Counter (Avr)#Allgemeine Funktionsweise|Allgemeine Funktionsweise]]&amp;quot; beschrieben. Die Zählrichtung des Timers ist immer aufsteigend, und irgendwann kommt es zu dem Interrupt Timer-Overflow (welcher in einer passend ISR aufgefangen werden kann). Im einfachsten Fall kann man diesen Modus in folgendem Diagramm darstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1.png]]&lt;br /&gt;
&lt;br /&gt;
Der Zähler des Timers (im Diagramm oben, die aufsteigende und dann wieder zurückgesetzte Linie) ist in dem Register TCNTx gespeichert, wobei x für eine Zahl steht. Soll z.B. auf den Timer0 (siehe Datenblatt des jeweiligen Controllers) des Controllers zugegriffen werden, so ist an TCNT eine 0 anzuhängen, also TCNT0.&lt;br /&gt;
Wie lange es braucht, bis der Zähler einen Overflow auslöst, ist von der Taktfrequenz des Controllers, dem eingestellten Prescaler-Wert und von der Timerauflösung abhängig. Nun wäre es ja sehr unpraktisch, wenn wir den Zähler nicht anpassen könnten. Denn sonst müssten wir unsere Software die den Timer benutzt evtl. anpassen und viel rechnen um z.B. für 1000 ms zu schlafen. Deswegen kann auf den Zähler zugreifen und ihn vorladen bevor dieser wieder vom eigentlichen Timer hochgezählt wird. Dies veranschaulicht folgendes Diagramm:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1_Vorladen.png]]&lt;br /&gt;
&lt;br /&gt;
Dadurch kann man den Timer beeinflussen, und beeinflussen wie lange es dauert, bis ein Overflow auftritt. Um zu berechnen, welchen Wert wir vorladen müssen, kann man auch ein Java-Applet nutzen, siehe unter [[Timer/Counter (Avr)#Weblinks|Weblinks Java Applet]].&lt;br /&gt;
&lt;br /&gt;
Natürlich kann man das auch &amp;quot;von Hand&amp;quot; rechnen. Die Berechnung des Preloader- sowie Prescalerwerts bei Verwendung der Overflow-Interrupts, eines Prescalers von 64 (nicht alle Prescaler können verwendet werden) und eines Quarzes mit der Frequenz von 8 MHz sieht folgendermaßen aus (gesuchte Frequenz beträgt 1000 Hz unter der Verwendung des Timer0 eines ATmega32):&lt;br /&gt;
# &amp;lt;math&amp;gt;Prescale = Frequenz * 1000000 [Hz] = 8000000&amp;lt;/math&amp;gt;&lt;br /&gt;
# Wir definieren den maximalen Zählerwert. Dieser ist bei einem 8-Bit Timer 256, bei einem 16-Bit Timer 65536. In unserem Fall ist der maximale Zählerwert 256, weil Timer0 verwendet wird.&lt;br /&gt;
# Nun wird die Variable ''Prescale'' (s.o.) durch den verwendeten Prescaler (64) geteilt (&amp;lt;math&amp;gt;8000000 Hz / 64 = 125000&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Als nächstes wird der im dritten Punkt errechnete Wert durch die gesuchte Frequenz geteilt &amp;lt;math&amp;gt;=125000 / 1000Hz = 125&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird mathematisch überprüft, ob der errechnete Wert aus dem vierten Punkt kleiner als der maximale Zählerwert ist. Trifft dies zu, so subtrahiert man den errechneten Wert vom maximalen Zählerwert (&amp;lt;math&amp;gt;= 256 - 125 = 131&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Damit haben wir den Wert errechnet, der bei jedem Interrupt, den der Timer0 auslöst, in TCNTx (in diesem Fall TCNT0) nachgeladen werden muss, damit die Interrupts in dem gewünschten Zeitabstand von einer Millisekunde ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
Allerdings bleibt zu bemerken, dass bei der Verwendung einer &amp;quot;ungeraden&amp;quot; Quarzfrequenz (z.B. 7,3728 MHz) der Timer mit einer bestimmten Ungenauigkeit arbeitet. Würden wir z.B. den Quarz oben mit einem Quarz mit 7,3728 MHz austauschen, so wäre die Fehlerrate 0,17%. Diese Ungeauigkeit varriert von verwendetem Prescaler zu Prescaler. D.h. wenn wir einen Prescaler von 1024 (und einer Quarzfrequenz von 8 MHz) verwendet hätten, so hätten wir eine inakzeptable Ungeauigkeit von 11,61%. Deswegen sollte sie eines der genannten Programme unter [[Avr#Weblinks]] verwenden, denn diese zeigen nur die bestmögliche Konfiguration an.&lt;br /&gt;
&lt;br /&gt;
Die Fehlerrate kann natürlich auch ausgerechnet werden. Hier die Rechenschritte (sie sind erweiternd zu der oberen Berechnung):&lt;br /&gt;
# Als erstes wird mathematisch überprüft, ob der Preloaderwert (siehe fünften Schritt oben) größer als 1 ist.&lt;br /&gt;
# Trifft dies zu, so wird als nächstes die resultierende Frequenz errechnet. Die geschieht folgendermaßen: Der errechnete Preloaderwert aus der Rechnung oben wird vom maximalen Zählerwert subtrahiert, anschließend mit dem Prescaler multipliziert und dann das Ganze durch die Variable Prescale geteilt &lt;br /&gt;
&amp;lt;math&amp;gt;(256 - 131) \cdot 64 / 8\,000\,000 \mathrm{Hz} \cdot 1\,000\,000 = 1000&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird die gesuchte Frequenz vom errechneten Wert aus dem dritten Punkt subtrahiert und dann wiederum durch diese geteilt &amp;lt;math&amp;gt;(1000-1000) / 1000 = 0&amp;lt;/math&amp;gt;. Damit läuft dieser Timer genau mit einer Fehlerrate von 0 %.&lt;br /&gt;
&lt;br /&gt;
Betreibt man den Timer im Overflow-Modus, so muss man, wie bereits erwähnt, nach/bei jedem Overflow-Interrupt den Timer nachladen. Der Interrupt heißt in diesem Fall SIG_OVERFLOWx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine&lt;br /&gt;
Frequenz von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und&lt;br /&gt;
einem Preloader von  183 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_SIG_OVERFLOW2)&lt;br /&gt;
{&lt;br /&gt;
	countTimer2++;&lt;br /&gt;
	TCNT2 = 183;		// Nachladen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22);		// Prescaler von 1&lt;br /&gt;
TCNT2  = 183;			// Vorladen&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;TOIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep (uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Allerdings wird auf diese leicht veraltete Technik nun nicht weiter eingegangen. Der Artikel wendet sich nun dem neueren &amp;quot;Compare Output&amp;quot;-Betriebsmodus zu.&lt;br /&gt;
&lt;br /&gt;
Beim &amp;quot;Compare Output&amp;quot;-Betriebsmodus wird genauso ein Zähler hochgezählt. Allerdings wird der Zählerwert nach jeder Inkrementierung mit einem vom Benutzer festgelegten Wert verglichen. Entspricht der Zählerwert dem gespeicherten Wert, so kommt es zu einem Interrupt. Dieser Wert wird in das Register OCRx (x steht wieder für die Timernummer) gespeichert. Je nach Auflösung des Timers ist dieses Register 8-Bit oder 16-Bit breit. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Siehe CTC Modus unten. Dieser wird benötigt um den Timer entsprechend im &amp;quot;Compare Output&amp;quot;-Betriebsmodus vernünftig zu betreiben.&lt;br /&gt;
&lt;br /&gt;
Hier ein typisches Diagramm dieses Betriebsmodus (Hinweis: Das Diagramm wurde unter Verwendung des CTC Modus erstellt. Für Begriffserklärung siehe CTC Modus):&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
Das Ausrechnen des Werts, der in OCRx geschrieben werden muss, damit Frequenz x entsteht, ist nicht sonderlich schwer. Man geht wie bei der Berechnung des Werts für den Overflow-Modus vor (s.o.) nur daß man das resultierende Ergebnis vom maximalen Zählerwert (bei 8-Bit Auflösung ist dieser 256, bei 16-Bit Auflösung 65536) subtrahiert. Das Ergebnis wird dann einmalig in das Register OCRx geschrieben. Mann muss also nicht wie beim Overflow-Modus den Timer nach jedem Interrupt nachladen. Der enstehende Interrupt heißt in diesem Fall SIG_OUTPUT_COMPAREx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Wiederum zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine Frequenz&lt;br /&gt;
von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und einem OCR2-Wert&lt;br /&gt;
von 73 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE2)&lt;br /&gt;
{&lt;br /&gt;
  countTimer2++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22) | (1&amp;lt;&amp;lt;WGM21);	// Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)&lt;br /&gt;
OCR2  = 73;			// Vergleichswert&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;OCIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep(uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CTC Modus (Clear Timer on Compare Match mode) ===&lt;br /&gt;
Der CTC Modus ist eine Erweiterung des &amp;quot;Compare Output&amp;quot;-Betriebsmodus. Der CTC Modus wird z.B. für das obere Beispielprogramm benötigt. Wird der Timer nämlich im normalen Betriebsmodus betrieben, so ist seine Zählergrenze je nach Auflösung 255 oder entsprechend für die 16-Bit Timer. Erst wenn diese Grenze erreicht wurde, wird der Timer zurückgesetzt (also auf 0). Durch den CTC Modus wird der Timer augenblicklich automatisch zurückgesetzt nachdem der Vergleichswert erreicht ist. Man kann also die maximalen Zählergrenze selber definieren.&lt;br /&gt;
Dieses Diagramm veranschaulicht den CTC Modus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
=== PWM ===&lt;br /&gt;
Für PWM siehe [[Pwm]].&lt;br /&gt;
&lt;br /&gt;
== Registerübersicht ==&lt;br /&gt;
''Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.''&lt;br /&gt;
&lt;br /&gt;
{| {{Blaueschmaltabelle}} width=100%&lt;br /&gt;
 |'''TIMSK'''&lt;br /&gt;
 |-&lt;br /&gt;
 |Mit diesem Register, der von allen Timern verwendet wird, lässt sich die Interruptausführung und Art des jeweiligen Timers bestimmen.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Registertabelle8Bit|OCIE2|TOIE2|TICIE1|OCIE1A|OCIE1B|TOIE1|OCIE0|TOIE0}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
*'''OCIE2 (Timer/Counter2 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE2 (Timer/Counter2 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TICIE1 (Timer/Counter1, Input Capture Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Input Capture Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1A (Timer/Counter1 Output Compare A Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare A Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1B (Timer/Counter1 Output Compare B Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare B Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE1 (Timer/Counter1 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE0 (Timer/Counter0 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Overflow Interrupt aktiviert  (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Atmel]]&lt;br /&gt;
* [[HEX Beispiel-Dateien für AVR]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]&lt;br /&gt;
* [https://mpg.dnsalias.com/~magerlu/rn-wiki/avrtimer_applet Java Applet Timer Berechnung] &lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Elektronik]]&lt;br /&gt;
[[Kategorie:Abkürzung|AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13876</id>
		<title>Timer/Counter (Avr)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&amp;diff=13876"/>
				<updated>2008-08-16T19:37:34Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Mikrocontroller der AVR-Familie besitzen je nach Typ eine unterschiedliche Anzahl an programmierbaren [[Timer|Timern]]. Bei den aktuellen ATmegas sind das mindestens ein 8-Bit Timer und bei größeren Ausführungen der Serie auch 16-Bit Timer. Die Timer werden immer Timerx benannt, wobei x für die Timernummer steht (also 0, 1, 2, usw.). &lt;br /&gt;
Die Konfigurationsmöglichkeiten sind von Timer zu Timer unterschiedlich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis:''' Die folgenden Code-Beispiele sind in C programmiert und wurden für einen [[ATMega32|ATmega32]] entwickelt. Sie lassen sich also ohne große Änderungen auch auf anderen Mikrocontrollern der AVR-Familie einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Funktionsweise ==&lt;br /&gt;
Timer funktionieren nach dem allgemeinen Prinzip, dass sie eine Ganzzahl (im weiteren als Zähler bezeichnet) je nach Betriebsmodus auf- oder abwärtszählen, d.h. inkrementieren bzw. dekrementieren.&lt;br /&gt;
&lt;br /&gt;
Angenommen, der Timer arbeitet im einfachsten Betriebsmodus, dem normalen Modus (siehe [[Avr#Normaler Modus (Normal Mode)|Normaler Modus (Normal Mode)]]). Die Zählrichtung des Timers ist aufsteigend gerichtet. Je nach Auflösung, also 8-Bit oder 16-Bit, erreicht der Zähler irgendwann einen bestimmten Zustand. Möglich wäre, dass er überläuft, wenn z.B. bei einem 8-Bit Timer der Wert 255 inkrementiert wird (siehe Grafik).&lt;br /&gt;
&lt;br /&gt;
[[Bild:AbstrakterZaehlvorgang.png]]&lt;br /&gt;
&lt;br /&gt;
== Der Prescaler ==&lt;br /&gt;
Der Prescaler (eng. = Vorteiler) kann dazu genutzt werden, den Takt, der den Timern zugeführt wird, zu verkleinern. U.a. kann man damit die Timer so konfigurieren, damit diese in den unterschiedlichsten Frequenzen takten. Hier eine Grafik die den Prescaler veranschaulicht:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Prescaler.png]]&lt;br /&gt;
&lt;br /&gt;
Das obere Diagramm zeigt den Betrieb ohne Prescaler, das untere mit Prescaler. Die gestrichelte Linie zeigt, wann ein Interrupt eintritt.&lt;br /&gt;
&lt;br /&gt;
Im Teil [[Avr#Die Betriebsmodi|Die Betriebsmodi]] wird weiter auf die praktische Verwendung des Prescalers eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Die Betriebsmodi ==&lt;br /&gt;
Die AVR-Timer können in unterschiedlichen Betriebsmodi betrieben werden. Diese sind:&lt;br /&gt;
* Normaler Modus&lt;br /&gt;
* CTC Modus&lt;br /&gt;
* PWM&lt;br /&gt;
&lt;br /&gt;
=== Normaler Modus (Normal Mode) ===&lt;br /&gt;
Der einfachste Betriebsmodus ist der normale Modus. Er funktioniert wie im Abschnitt  &amp;quot;[[Avr#Allgemeine Funktionsweise|Allgemeine Funktionsweise]]&amp;quot; beschrieben. Die Zählrichtung des Timers ist immer aufsteigend, und irgendwann kommt es zu dem Interrupt Timer-Overflow (welcher in einer passend ISR aufgefangen werden kann). Im einfachsten Fall kann man diesen Modus in folgendem Diagramm darstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1.png]]&lt;br /&gt;
&lt;br /&gt;
Der Zähler des Timers (im Diagramm oben, die aufsteigende und dann wieder zurückgesetzte Linie) ist in dem Register TCNTx gespeichert, wobei x für eine Zahl steht. Soll z.B. auf den Timer0 (siehe Datenblatt des jeweiligen Controllers) des Controllers zugegriffen werden, so ist an TCNT eine 0 anzuhängen, also TCNT0.&lt;br /&gt;
Wie lange es braucht, bis der Zähler einen Overflow auslöst, ist von der Taktfrequenz des Controllers, dem eingestellten Prescaler-Wert und von der Timerauflösung abhängig. Nun wäre es ja sehr unpraktisch, wenn wir den Zähler nicht anpassen könnten. Denn sonst müssten wir unsere Software die den Timer benutzt evtl. anpassen und viel rechnen um z.B. für 1000 ms zu schlafen. Deswegen kann auf den Zähler zugreifen und ihn vorladen bevor dieser wieder vom eigentlichen Timer hochgezählt wird. Dies veranschaulicht folgendes Diagramm:&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_1_Vorladen.png]]&lt;br /&gt;
&lt;br /&gt;
Dadurch kann man den Timer beeinflussen, und beeinflussen wie lange es dauert, bis ein Overflow auftritt. Um zu berechnen, welchen Wert wir vorladen müssen, kann man auch ein Java-Applet nutzen, siehe unter [[Avr#Weblinks|Weblinks Java Applet]].&lt;br /&gt;
&lt;br /&gt;
Natürlich kann man das auch &amp;quot;von Hand&amp;quot; rechnen. Die Berechnung des Preloader- sowie Prescalerwerts bei Verwendung der Overflow-Interrupts, eines Prescalers von 64 (nicht alle Prescaler können verwendet werden) und eines Quarzes mit der Frequenz von 8 MHz sieht folgendermaßen aus (gesuchte Frequenz beträgt 1000 Hz unter der Verwendung des Timer0 eines ATmega32):&lt;br /&gt;
# &amp;lt;math&amp;gt;Prescale = Frequenz * 1000000 [Hz] = 8000000&amp;lt;/math&amp;gt;&lt;br /&gt;
# Wir definieren den maximalen Zählerwert. Dieser ist bei einem 8-Bit Timer 256, bei einem 16-Bit Timer 65536. In unserem Fall ist der maximale Zählerwert 256, weil Timer0 verwendet wird.&lt;br /&gt;
# Nun wird die Variable ''Prescale'' (s.o.) durch den verwendeten Prescaler (64) geteilt (&amp;lt;math&amp;gt;8000000 Hz / 64 = 125000&amp;lt;/math&amp;gt;).&lt;br /&gt;
# Als nächstes wird der im dritten Punkt errechnete Wert durch die gesuchte Frequenz geteilt &amp;lt;math&amp;gt;=125000 / 1000Hz = 125&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird mathematisch überprüft, ob der errechnete Wert aus dem vierten Punkt kleiner als der maximale Zählerwert ist. Trifft dies zu, so subtrahiert man den errechneten Wert vom maximalen Zählerwert (&amp;lt;math&amp;gt;= 256 - 125 = 131&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Damit haben wir den Wert errechnet, der bei jedem Interrupt, den der Timer0 auslöst, in TCNTx (in diesem Fall TCNT0) nachgeladen werden muss, damit die Interrupts in dem gewünschten Zeitabstand von einer Millisekunde ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
Allerdings bleibt zu bemerken, dass bei der Verwendung einer &amp;quot;ungeraden&amp;quot; Quarzfrequenz (z.B. 7,3728 MHz) der Timer mit einer bestimmten Ungenauigkeit arbeitet. Würden wir z.B. den Quarz oben mit einem Quarz mit 7,3728 MHz austauschen, so wäre die Fehlerrate 0,17%. Diese Ungeauigkeit varriert von verwendetem Prescaler zu Prescaler. D.h. wenn wir einen Prescaler von 1024 (und einer Quarzfrequenz von 8 MHz) verwendet hätten, so hätten wir eine inakzeptable Ungeauigkeit von 11,61%. Deswegen sollte sie eines der genannten Programme unter [[Avr#Weblinks]] verwenden, denn diese zeigen nur die bestmögliche Konfiguration an.&lt;br /&gt;
&lt;br /&gt;
Die Fehlerrate kann natürlich auch ausgerechnet werden. Hier die Rechenschritte (sie sind erweiternd zu der oberen Berechnung):&lt;br /&gt;
# Als erstes wird mathematisch überprüft, ob der Preloaderwert (siehe fünften Schritt oben) größer als 1 ist.&lt;br /&gt;
# Trifft dies zu, so wird als nächstes die resultierende Frequenz errechnet. Die geschieht folgendermaßen: Der errechnete Preloaderwert aus der Rechnung oben wird vom maximalen Zählerwert subtrahiert, anschließend mit dem Prescaler multipliziert und dann das Ganze durch die Variable Prescale geteilt &lt;br /&gt;
&amp;lt;math&amp;gt;(256 - 131) \cdot 64 / 8\,000\,000 \mathrm{Hz} \cdot 1\,000\,000 = 1000&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Nun wird die gesuchte Frequenz vom errechneten Wert aus dem dritten Punkt subtrahiert und dann wiederum durch diese geteilt &amp;lt;math&amp;gt;(1000-1000) / 1000 = 0&amp;lt;/math&amp;gt;. Damit läuft dieser Timer genau mit einer Fehlerrate von 0 %.&lt;br /&gt;
&lt;br /&gt;
Betreibt man den Timer im Overflow-Modus, so muss man, wie bereits erwähnt, nach/bei jedem Overflow-Interrupt den Timer nachladen. Der Interrupt heißt in diesem Fall SIG_OVERFLOWx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine&lt;br /&gt;
Frequenz von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und&lt;br /&gt;
einem Preloader von  183 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_SIG_OVERFLOW2)&lt;br /&gt;
{&lt;br /&gt;
	countTimer2++;&lt;br /&gt;
	TCNT2 = 183;		// Nachladen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22);		// Prescaler von 1&lt;br /&gt;
TCNT2  = 183;			// Vorladen&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;TOIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep (uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Allerdings wird auf diese leicht veraltete Technik nun nicht weiter eingegangen. Der Artikel wendet sich nun dem neueren &amp;quot;Compare Output&amp;quot;-Betriebsmodus zu.&lt;br /&gt;
&lt;br /&gt;
Beim &amp;quot;Compare Output&amp;quot;-Betriebsmodus wird genauso ein Zähler hochgezählt. Allerdings wird der Zählerwert nach jeder Inkrementierung mit einem vom Benutzer festgelegten Wert verglichen. Entspricht der Zählerwert dem gespeicherten Wert, so kommt es zu einem Interrupt. Dieser Wert wird in das Register OCRx (x steht wieder für die Timernummer) gespeichert. Je nach Auflösung des Timers ist dieses Register 8-Bit oder 16-Bit breit. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Siehe CTC Modus unten. Dieser wird benötigt um den Timer entsprechend im &amp;quot;Compare Output&amp;quot;-Betriebsmodus vernünftig zu betreiben.&lt;br /&gt;
&lt;br /&gt;
Hier ein typisches Diagramm dieses Betriebsmodus (Hinweis: Das Diagramm wurde unter Verwendung des CTC Modus erstellt. Für Begriffserklärung siehe CTC Modus):&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
Das Ausrechnen des Werts, der in OCRx geschrieben werden muss, damit Frequenz x entsteht, ist nicht sonderlich schwer. Man geht wie bei der Berechnung des Werts für den Overflow-Modus vor (s.o.) nur daß man das resultierende Ergebnis vom maximalen Zählerwert (bei 8-Bit Auflösung ist dieser 256, bei 16-Bit Auflösung 65536) subtrahiert. Das Ergebnis wird dann einmalig in das Register OCRx geschrieben. Mann muss also nicht wie beim Overflow-Modus den Timer nach jedem Interrupt nachladen. Der enstehende Interrupt heißt in diesem Fall SIG_OUTPUT_COMPAREx (x steht für die Nummer des Timers). Dieser muss in einer ISR abgefangen werden.&lt;br /&gt;
&lt;br /&gt;
Wiederum zusammenfassend ein Beispielprogramm:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz&lt;br /&gt;
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine Frequenz&lt;br /&gt;
von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und einem OCR2-Wert&lt;br /&gt;
von 73 konfiguriert.*/&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t countTimer2;	// Speichert den aktuellen Zählerwert&lt;br /&gt;
&lt;br /&gt;
// ISR zum auffangen der Interrupts:&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE2)&lt;br /&gt;
{&lt;br /&gt;
  countTimer2++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialisierung:&lt;br /&gt;
TCCR2 = (1&amp;lt;&amp;lt;CS22) | (1&amp;lt;&amp;lt;WGM21);	// Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)&lt;br /&gt;
OCR2  = 73;			// Vergleichswert&lt;br /&gt;
TIMSK |= (1&amp;lt;&amp;lt;OCIE2);		// Interrupts aktivieren und damit Timer starten&lt;br /&gt;
sei();&lt;br /&gt;
&lt;br /&gt;
// Funktionen zum benutzen der Timer:&lt;br /&gt;
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.&lt;br /&gt;
Bei t=100 schläft die Funktion 1 ms. */&lt;br /&gt;
inline void sleep(uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
	// countTimer2 wird in der ISR oben inkrementiert&lt;br /&gt;
	countTimer2 = 0;&lt;br /&gt;
	while (countTimer2 &amp;lt; t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** Schläft x-Millisekunden. */&lt;br /&gt;
inline void sleep_millisec(uint16_t msec)&lt;br /&gt;
{&lt;br /&gt;
	uint16_t i;&lt;br /&gt;
	for(i=0; i&amp;lt;msec; i++) {&lt;br /&gt;
		sleep(100);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CTC Modus (Clear Timer on Compare Match mode) ===&lt;br /&gt;
Der CTC Modus ist eine Erweiterung des &amp;quot;Compare Output&amp;quot;-Betriebsmodus. Der CTC Modus wird z.B. für das obere Beispielprogramm benötigt. Wird der Timer nämlich im normalen Betriebsmodus betrieben, so ist seine Zählergrenze je nach Auflösung 255 oder entsprechend für die 16-Bit Timer. Erst wenn diese Grenze erreicht wurde, wird der Timer zurückgesetzt (also auf 0). Durch den CTC Modus wird der Timer augenblicklich automatisch zurückgesetzt nachdem der Vergleichswert erreicht ist. Man kann also die maximalen Zählergrenze selber definieren.&lt;br /&gt;
Dieses Diagramm veranschaulicht den CTC Modus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:NormalerModus_CompareMatch.png]]&lt;br /&gt;
&lt;br /&gt;
=== PWM ===&lt;br /&gt;
Für PWM siehe [[Pwm]].&lt;br /&gt;
&lt;br /&gt;
== Registerübersicht ==&lt;br /&gt;
''Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.''&lt;br /&gt;
&lt;br /&gt;
{| {{Blaueschmaltabelle}} width=100%&lt;br /&gt;
 |'''TIMSK'''&lt;br /&gt;
 |-&lt;br /&gt;
 |Mit diesem Register, der von allen Timern verwendet wird, lässt sich die Interruptausführung und Art des jeweiligen Timers bestimmen.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Registertabelle8Bit|OCIE2|TOIE2|TICIE1|OCIE1A|OCIE1B|TOIE1|OCIE0|TOIE0}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
*'''OCIE2 (Timer/Counter2 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE2 (Timer/Counter2 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TICIE1 (Timer/Counter1, Input Capture Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Input Capture Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1A (Timer/Counter1 Output Compare A Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare A Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE1B (Timer/Counter1 Output Compare B Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare B Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE1 (Timer/Counter1 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
*'''TOIE0 (Timer/Counter0 Overflow Interrupt Enable)'''&amp;lt;br/&amp;gt;Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Overflow Interrupt aktiviert  (vorrausgesetzt die Interrupts sind global aktiviert).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Atmel]]&lt;br /&gt;
* [[HEX Beispiel-Dateien für AVR]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]&lt;br /&gt;
* [https://mpg.dnsalias.com/~magerlu/rn-wiki/avrtimer_applet Java Applet Timer Berechnung] &lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Elektronik]]&lt;br /&gt;
[[Kategorie:Abkürzung|AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=R%C3%A4der_an_der_Motorwelle_befestigen_(Welle/Nabe-Verbindung)&amp;diff=13829</id>
		<title>Räder an der Motorwelle befestigen (Welle/Nabe-Verbindung)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=R%C3%A4der_an_der_Motorwelle_befestigen_(Welle/Nabe-Verbindung)&amp;diff=13829"/>
				<updated>2008-08-08T16:18:02Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Befestigung mit einem speziellen Felgenadapter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Für fahrbare Roboter werden oft die unterschiedlichsten Räder genutzt. Entweder Modellbauräder, Räder aus dem Baumarkt oder Eigenkonstruktionen (z.B. umfunktionierte CDs). Wie auch immer, die einzelnen Räder haben gewöhnlich völlig unterschiedliche Bohrlöcher für die Achse. Dies schwankt duchaus von 4 mm bis 12mm. Übliche Getriebemotoren und Schrittmotoren dagegen haben oft eine 4-mm-,5-mm- oder 6-mm-Achse. &lt;br /&gt;
Die Befestigung des Rades an der Motorwelle ist daher oft das erste Problem vor dem ein Robotik-Bastler steht.&lt;br /&gt;
&lt;br /&gt;
Es gibt unzählige verschiedene Möglichkeiten zur Befestigung eines Rades. Einige Lösungen werden nun hier vorgestellt. Dabei sagen die Bilder mehr als tausend Worte.&lt;br /&gt;
&lt;br /&gt;
Einige Hilfmittel, die im Handel angeboten werden, um die Befestigung zu erleichtern. Auf dem Bild sehen Sie z.B. Potikupplungen, Propellernaben und spezielle Modellbaubefestigungen für sehr große Räder.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen.jpg|Verschiedene Hilfsmittel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einfache Möglichkeit mittels Gewindestange und Achskupplung==&lt;br /&gt;
Eine besonders einfache Möglichkeit ist die Verwendung einer kurzen Gewindestange. Dabei kann man je nach Bohrloch des Rades einfach eine Gewindestange entsprechenden Durchmessers verwenden und das Rad mit gegenläufigen Muttern auf beiden Seiten festschrauben. Bei besonders schweren Robotern kann ein Tropfen Sekundenkleber zudem noch das Durchdrehen bei starker Belastung verhindern. Die Gewindestange selbst kann man einfach über eine Kupplung an der Welle befestigen.&lt;br /&gt;
Im Handel gibt es spezielle Wellenkupplungen für diese Aufgabe, jedoch sind die professionellen Ausführungen recht teuer (oft über 20 Euro pro Stück, ähnlich nachfolgender Abbildung).&lt;br /&gt;
&lt;br /&gt;
[[Bild:wellenkupplung.jpeg]]&lt;br /&gt;
[[Bild:wellenkupplung2.jpeg]]&lt;br /&gt;
&lt;br /&gt;
In der Praxis hat sich für Bastler eine preiswerte Lösung mit Potikupplungen als durchaus sinnvoll erwiesen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:kupplung6.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Potikupplungen gibt es bei vielen Anbietern (Conrad, Reichelt, robotikhardware usw.) für 6 mm auf 6-mm-Achsen und 4 mm auf 6-mm-Achsen. Da die meisten Motoren eine 6-mm-Achse besitzen, ist dies also eine gute Lösung. Die Bilder zeigen, wie ein Modellbaurad mit 4-mm-Loch an einem Motor mit 6-mm-Achse befestigt wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplung1.jpg|center|Gewindestange mit Welle verbinden]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung2.jpg|center|Gewindestange verschrauben]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung3.jpg|center]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung4.jpg|center]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ könnte man natürlich die 4-mm-Bohrung im Modellbaurad auch sehr leicht mit einem 6-mm-Bohrer auf 6 mm erweitern und dann eine 6- auf 6-mm-Kupplung verwenden. Die Lösung eignet sich natürlich für Schritt- als auch Getriebemotoren. Je nach Befestigung des Motors und vorhandenem Platz kann man natürlich das Rad auch umgekehrt befestigen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplung5.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Auf dem nachfolgenden Foto sieht man, wie die Befestigung von Motor und Rad nach oben beschriebener Methode aussehen könnte. Statt dem Stückchen Gewindestange wurde hier einfach eine Gewindeschraube genutzt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_pebisoft.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Einfache Alternative mit Propellernaben==&lt;br /&gt;
Auch sogenannte Propellernaben lassen sich sehr gut zur Befestigung  von Rädern nutzen. Damit lassen sich sehr gut auch größere Räder (Dinge) an kleinen Achsen wie 3 mm oder 5 mm befestigen. Leider gibt es wohl keine Propellernaben mit 6-mm-Innenloch. Da viele jedoch aus leichtem Aluminium bestehen, kann man das Innenloch durchaus mit einem Bohrer auf 6 mm erweitern. Die Befestigung an der Welle erfolgt immer per Madenschraube oder notfalls Sekundenkleber. Der Außendurchmesser der Propellernabe ist in der Regel 8 mm. Dadurch lassen sich also schon eine ganze Reihe von Rädern direkt mit einer Mutter anschrauben. &lt;br /&gt;
Die nachfolgenden Bilder zeigen, wie man sehr große Modellbauräder mit einem großen 12-mm-Loch durchaus auch sehr leicht mit Propellernabe und spezieller Modellbauradbefestigung an kleinen 5-mm- oder 6-mm-Achsen befestigt. Die Propellernaben stammen von Conrad Elektronik.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_b.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_c.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_d.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_e.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_f.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_g.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Auf den Bildern wurden nur Muttern zur Befestigung genutzt. Bei schweren Robotern sollte die Welle durchbohrt und der mitgelieferte Splint eingesetzt werden. Dadurch wird ein Durchdrehen oder Lösen der Muttern verhindert. Ein Tropfen Sekundenkleber erreicht das Gleiche, jedoch bekommt man dies dann selbst nie mehr auseinander.&lt;br /&gt;
&lt;br /&gt;
Auf dem Bild sehen wir, das Propellernaben durchaus auch bei Motoren mit sehr kleinem Wellendurchmesser eingesetzt werden können:&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_h.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Umgehen der direkten Befestigung des Rades==&lt;br /&gt;
Man kann natürlich das Problem der Radbefestigung auch ganz einfach umgehen indem man die Räder auf einer anderen Welle / Getriebestange befestigt und die Verbindung einfach über ein Zahnriemenrad herstellt. Zahnriemenräder gibt es für viele Achsdurchmesser, die Befestigung ist oft mittels Madenschraube sehr einfach möglich. Wenn man dann noch die Räder auf einer Gewindestange statt Stahlwelle befestigt, ist das Ganze sehr einfach zu realisieren. Die Gewindestange kann man dann über Kugellager auf beiden Seiten lagern. Der Fachmann wird eine Gewindestange als Welle in der Regel nicht nutzen oder empfehlen, weil dadurch mit der Zeit die Lager beschädigt werden können und die Reibung nicht ganz optimal ist. Allerdings ist in der Praxis die Lösung durchaus für viele Dinge ausreichend und übersteht oft die übliche Lebensdauer eines Hobby-Roboters. &lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_j.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Befestigung durch Aufbohren einer Gewindestange==&lt;br /&gt;
Bei dem nachfolgenden Bild wurde ein 6-mm-Loch in eine größere Gewindestange gebohrt. Zusätzlich wurde ein kleines Loch für eine Art Madenschraube gebohrt und mit Gewinde versehen. Dadurch läßt sich die Gewindestange direkt auf die Welle aufstecken und mittels Schraube befestigen. Das Rad selbst kann wieder mit gegenläufigen Muttern angeschraubt werden. Diese Lösung ist sehr günstig, erfordert jedoch ein wenig mechanisches Geschick.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_lukas.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Befestigung mit einem speziellen Felgenadapter==&lt;br /&gt;
Die recht beliebten Räder aus dem RC-Modellbaubereich (wie sie auch bei den Fotos zu den anderen Befestigungsmöglichkeiten zu sehen sind) haben an der Innenseite eine 12mm-Sechskantaufnahme. Hier lässt sich ein Adapterstück mit einem 12mm-Sechskantprofil und einer Bohrung für die Motorwelle anbringen. Dies ergibt eine stabile und kraftschlüssige Befestigung. Ein solches Adapterstück ist jedoch ohne teures Werkzeug (Fräse, Drehmaschine) nicht gerade einfach anzufertigen, da schon etliches an Präzision gefragt ist, damit die Räder nicht eiern. Es gibt jedoch mittlerweile einen Anbieter *) für Adapter aus Edelstahl. Die Bohrung ist 6mm groß, was auf viele Getriebemotoren passt. &lt;br /&gt;
&lt;br /&gt;
 *) [http://www.embedit.de embedit.de], mittlerweile sind diese Adapter dort leider nicht mehr erhältlich!&lt;br /&gt;
 Fragt aber ruhig mal nach, falls ihr welche gebrauchen könntet. Vielleicht werden sie ja irgendwann&lt;br /&gt;
 mal wieder angeboten, wenn genügend Leute nachfragen...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:radadapter.jpg|center|thumb|400px|Anwendungsbeispiel Radadapter]]&lt;br /&gt;
&lt;br /&gt;
==Weitere Lösungen==&lt;br /&gt;
Es gibt noch eine ganze Reihe weiterer Lösungen, wie das einfache Ankleben oder Schneiden von Außengewinde auf eine Welle. Gerne kann jeder weitere hier im Artikel erläutern. &lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Frank|Frank]] 14:40, 14. Nov 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
[[Category:Robotikeinstieg]]&lt;br /&gt;
[[Category:Praxis]]&lt;br /&gt;
[[Category:Mechanik]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=R%C3%A4der_an_der_Motorwelle_befestigen_(Welle/Nabe-Verbindung)&amp;diff=13828</id>
		<title>Räder an der Motorwelle befestigen (Welle/Nabe-Verbindung)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=R%C3%A4der_an_der_Motorwelle_befestigen_(Welle/Nabe-Verbindung)&amp;diff=13828"/>
				<updated>2008-08-08T16:16:28Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Befestigung mit einem speziellen Felgenadapter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Für fahrbare Roboter werden oft die unterschiedlichsten Räder genutzt. Entweder Modellbauräder, Räder aus dem Baumarkt oder Eigenkonstruktionen (z.B. umfunktionierte CDs). Wie auch immer, die einzelnen Räder haben gewöhnlich völlig unterschiedliche Bohrlöcher für die Achse. Dies schwankt duchaus von 4 mm bis 12mm. Übliche Getriebemotoren und Schrittmotoren dagegen haben oft eine 4-mm-,5-mm- oder 6-mm-Achse. &lt;br /&gt;
Die Befestigung des Rades an der Motorwelle ist daher oft das erste Problem vor dem ein Robotik-Bastler steht.&lt;br /&gt;
&lt;br /&gt;
Es gibt unzählige verschiedene Möglichkeiten zur Befestigung eines Rades. Einige Lösungen werden nun hier vorgestellt. Dabei sagen die Bilder mehr als tausend Worte.&lt;br /&gt;
&lt;br /&gt;
Einige Hilfmittel, die im Handel angeboten werden, um die Befestigung zu erleichtern. Auf dem Bild sehen Sie z.B. Potikupplungen, Propellernaben und spezielle Modellbaubefestigungen für sehr große Räder.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen.jpg|Verschiedene Hilfsmittel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einfache Möglichkeit mittels Gewindestange und Achskupplung==&lt;br /&gt;
Eine besonders einfache Möglichkeit ist die Verwendung einer kurzen Gewindestange. Dabei kann man je nach Bohrloch des Rades einfach eine Gewindestange entsprechenden Durchmessers verwenden und das Rad mit gegenläufigen Muttern auf beiden Seiten festschrauben. Bei besonders schweren Robotern kann ein Tropfen Sekundenkleber zudem noch das Durchdrehen bei starker Belastung verhindern. Die Gewindestange selbst kann man einfach über eine Kupplung an der Welle befestigen.&lt;br /&gt;
Im Handel gibt es spezielle Wellenkupplungen für diese Aufgabe, jedoch sind die professionellen Ausführungen recht teuer (oft über 20 Euro pro Stück, ähnlich nachfolgender Abbildung).&lt;br /&gt;
&lt;br /&gt;
[[Bild:wellenkupplung.jpeg]]&lt;br /&gt;
[[Bild:wellenkupplung2.jpeg]]&lt;br /&gt;
&lt;br /&gt;
In der Praxis hat sich für Bastler eine preiswerte Lösung mit Potikupplungen als durchaus sinnvoll erwiesen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:kupplung6.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Potikupplungen gibt es bei vielen Anbietern (Conrad, Reichelt, robotikhardware usw.) für 6 mm auf 6-mm-Achsen und 4 mm auf 6-mm-Achsen. Da die meisten Motoren eine 6-mm-Achse besitzen, ist dies also eine gute Lösung. Die Bilder zeigen, wie ein Modellbaurad mit 4-mm-Loch an einem Motor mit 6-mm-Achse befestigt wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplung1.jpg|center|Gewindestange mit Welle verbinden]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung2.jpg|center|Gewindestange verschrauben]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung3.jpg|center]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung4.jpg|center]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ könnte man natürlich die 4-mm-Bohrung im Modellbaurad auch sehr leicht mit einem 6-mm-Bohrer auf 6 mm erweitern und dann eine 6- auf 6-mm-Kupplung verwenden. Die Lösung eignet sich natürlich für Schritt- als auch Getriebemotoren. Je nach Befestigung des Motors und vorhandenem Platz kann man natürlich das Rad auch umgekehrt befestigen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplung5.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Auf dem nachfolgenden Foto sieht man, wie die Befestigung von Motor und Rad nach oben beschriebener Methode aussehen könnte. Statt dem Stückchen Gewindestange wurde hier einfach eine Gewindeschraube genutzt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_pebisoft.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Einfache Alternative mit Propellernaben==&lt;br /&gt;
Auch sogenannte Propellernaben lassen sich sehr gut zur Befestigung  von Rädern nutzen. Damit lassen sich sehr gut auch größere Räder (Dinge) an kleinen Achsen wie 3 mm oder 5 mm befestigen. Leider gibt es wohl keine Propellernaben mit 6-mm-Innenloch. Da viele jedoch aus leichtem Aluminium bestehen, kann man das Innenloch durchaus mit einem Bohrer auf 6 mm erweitern. Die Befestigung an der Welle erfolgt immer per Madenschraube oder notfalls Sekundenkleber. Der Außendurchmesser der Propellernabe ist in der Regel 8 mm. Dadurch lassen sich also schon eine ganze Reihe von Rädern direkt mit einer Mutter anschrauben. &lt;br /&gt;
Die nachfolgenden Bilder zeigen, wie man sehr große Modellbauräder mit einem großen 12-mm-Loch durchaus auch sehr leicht mit Propellernabe und spezieller Modellbauradbefestigung an kleinen 5-mm- oder 6-mm-Achsen befestigt. Die Propellernaben stammen von Conrad Elektronik.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_b.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_c.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_d.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_e.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_f.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_g.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Auf den Bildern wurden nur Muttern zur Befestigung genutzt. Bei schweren Robotern sollte die Welle durchbohrt und der mitgelieferte Splint eingesetzt werden. Dadurch wird ein Durchdrehen oder Lösen der Muttern verhindert. Ein Tropfen Sekundenkleber erreicht das Gleiche, jedoch bekommt man dies dann selbst nie mehr auseinander.&lt;br /&gt;
&lt;br /&gt;
Auf dem Bild sehen wir, das Propellernaben durchaus auch bei Motoren mit sehr kleinem Wellendurchmesser eingesetzt werden können:&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_h.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Umgehen der direkten Befestigung des Rades==&lt;br /&gt;
Man kann natürlich das Problem der Radbefestigung auch ganz einfach umgehen indem man die Räder auf einer anderen Welle / Getriebestange befestigt und die Verbindung einfach über ein Zahnriemenrad herstellt. Zahnriemenräder gibt es für viele Achsdurchmesser, die Befestigung ist oft mittels Madenschraube sehr einfach möglich. Wenn man dann noch die Räder auf einer Gewindestange statt Stahlwelle befestigt, ist das Ganze sehr einfach zu realisieren. Die Gewindestange kann man dann über Kugellager auf beiden Seiten lagern. Der Fachmann wird eine Gewindestange als Welle in der Regel nicht nutzen oder empfehlen, weil dadurch mit der Zeit die Lager beschädigt werden können und die Reibung nicht ganz optimal ist. Allerdings ist in der Praxis die Lösung durchaus für viele Dinge ausreichend und übersteht oft die übliche Lebensdauer eines Hobby-Roboters. &lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_j.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Befestigung durch Aufbohren einer Gewindestange==&lt;br /&gt;
Bei dem nachfolgenden Bild wurde ein 6-mm-Loch in eine größere Gewindestange gebohrt. Zusätzlich wurde ein kleines Loch für eine Art Madenschraube gebohrt und mit Gewinde versehen. Dadurch läßt sich die Gewindestange direkt auf die Welle aufstecken und mittels Schraube befestigen. Das Rad selbst kann wieder mit gegenläufigen Muttern angeschraubt werden. Diese Lösung ist sehr günstig, erfordert jedoch ein wenig mechanisches Geschick.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_lukas.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Befestigung mit einem speziellen Felgenadapter==&lt;br /&gt;
Die recht beliebten Räder aus dem RC-Modellbaubereich (wie sie auch bei den Fotos zu den anderen Befestigungsmöglichkeiten zu sehen sind) haben an der Innenseite eine 12mm-Sechskantaufnahme. Hier lässt sich ein Adapterstück mit einem 12mm-Sechskantprofil und einer Bohrung für die Motorwelle anbringen. Dies ergibt eine stabile und kraftschlüssige Befestigung. Ein solches Adapterstück ist jedoch ohne teures Werkzeug (Fräse, Drehmaschine) nicht gerade einfach anzufertigen, da schon etliches an Präzision gefragt ist, damit die Räder nicht eiern. Es gibt jedoch mittlerweile einen Anbieter *) für Adapter aus Edelstahl. Die Bohrung ist 6mm groß, was auf viele Getriebemotoren passt. &lt;br /&gt;
&lt;br /&gt;
 *) [http://www.embedit.de embedit.de], mittlerweile sind diese Adapter dort leider nicht mehr erhältlich! Fragt aber ruhig mal nach, falls ihr welche gebrauchen könntet. Vielleicht werden sie ja irgendwann mal wieder angeboten, wenn genügend Leute nachfragen...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:radadapter.jpg|center|thumb|400px|Anwendungsbeispiel Radadapter]]&lt;br /&gt;
&lt;br /&gt;
==Weitere Lösungen==&lt;br /&gt;
Es gibt noch eine ganze Reihe weiterer Lösungen, wie das einfache Ankleben oder Schneiden von Außengewinde auf eine Welle. Gerne kann jeder weitere hier im Artikel erläutern. &lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Frank|Frank]] 14:40, 14. Nov 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
[[Category:Robotikeinstieg]]&lt;br /&gt;
[[Category:Praxis]]&lt;br /&gt;
[[Category:Mechanik]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=R%C3%A4der_an_der_Motorwelle_befestigen_(Welle/Nabe-Verbindung)&amp;diff=13827</id>
		<title>Räder an der Motorwelle befestigen (Welle/Nabe-Verbindung)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=R%C3%A4der_an_der_Motorwelle_befestigen_(Welle/Nabe-Verbindung)&amp;diff=13827"/>
				<updated>2008-08-08T16:08:48Z</updated>
		
		<summary type="html">&lt;p&gt;Uwegw: /* Befestigung mit einem speziellen Felgenadapter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Für fahrbare Roboter werden oft die unterschiedlichsten Räder genutzt. Entweder Modellbauräder, Räder aus dem Baumarkt oder Eigenkonstruktionen (z.B. umfunktionierte CDs). Wie auch immer, die einzelnen Räder haben gewöhnlich völlig unterschiedliche Bohrlöcher für die Achse. Dies schwankt duchaus von 4 mm bis 12mm. Übliche Getriebemotoren und Schrittmotoren dagegen haben oft eine 4-mm-,5-mm- oder 6-mm-Achse. &lt;br /&gt;
Die Befestigung des Rades an der Motorwelle ist daher oft das erste Problem vor dem ein Robotik-Bastler steht.&lt;br /&gt;
&lt;br /&gt;
Es gibt unzählige verschiedene Möglichkeiten zur Befestigung eines Rades. Einige Lösungen werden nun hier vorgestellt. Dabei sagen die Bilder mehr als tausend Worte.&lt;br /&gt;
&lt;br /&gt;
Einige Hilfmittel, die im Handel angeboten werden, um die Befestigung zu erleichtern. Auf dem Bild sehen Sie z.B. Potikupplungen, Propellernaben und spezielle Modellbaubefestigungen für sehr große Räder.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen.jpg|Verschiedene Hilfsmittel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einfache Möglichkeit mittels Gewindestange und Achskupplung==&lt;br /&gt;
Eine besonders einfache Möglichkeit ist die Verwendung einer kurzen Gewindestange. Dabei kann man je nach Bohrloch des Rades einfach eine Gewindestange entsprechenden Durchmessers verwenden und das Rad mit gegenläufigen Muttern auf beiden Seiten festschrauben. Bei besonders schweren Robotern kann ein Tropfen Sekundenkleber zudem noch das Durchdrehen bei starker Belastung verhindern. Die Gewindestange selbst kann man einfach über eine Kupplung an der Welle befestigen.&lt;br /&gt;
Im Handel gibt es spezielle Wellenkupplungen für diese Aufgabe, jedoch sind die professionellen Ausführungen recht teuer (oft über 20 Euro pro Stück, ähnlich nachfolgender Abbildung).&lt;br /&gt;
&lt;br /&gt;
[[Bild:wellenkupplung.jpeg]]&lt;br /&gt;
[[Bild:wellenkupplung2.jpeg]]&lt;br /&gt;
&lt;br /&gt;
In der Praxis hat sich für Bastler eine preiswerte Lösung mit Potikupplungen als durchaus sinnvoll erwiesen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:kupplung6.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Potikupplungen gibt es bei vielen Anbietern (Conrad, Reichelt, robotikhardware usw.) für 6 mm auf 6-mm-Achsen und 4 mm auf 6-mm-Achsen. Da die meisten Motoren eine 6-mm-Achse besitzen, ist dies also eine gute Lösung. Die Bilder zeigen, wie ein Modellbaurad mit 4-mm-Loch an einem Motor mit 6-mm-Achse befestigt wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplung1.jpg|center|Gewindestange mit Welle verbinden]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung2.jpg|center|Gewindestange verschrauben]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung3.jpg|center]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:achskupplung4.jpg|center]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ könnte man natürlich die 4-mm-Bohrung im Modellbaurad auch sehr leicht mit einem 6-mm-Bohrer auf 6 mm erweitern und dann eine 6- auf 6-mm-Kupplung verwenden. Die Lösung eignet sich natürlich für Schritt- als auch Getriebemotoren. Je nach Befestigung des Motors und vorhandenem Platz kann man natürlich das Rad auch umgekehrt befestigen. &lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplung5.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Auf dem nachfolgenden Foto sieht man, wie die Befestigung von Motor und Rad nach oben beschriebener Methode aussehen könnte. Statt dem Stückchen Gewindestange wurde hier einfach eine Gewindeschraube genutzt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_pebisoft.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Einfache Alternative mit Propellernaben==&lt;br /&gt;
Auch sogenannte Propellernaben lassen sich sehr gut zur Befestigung  von Rädern nutzen. Damit lassen sich sehr gut auch größere Räder (Dinge) an kleinen Achsen wie 3 mm oder 5 mm befestigen. Leider gibt es wohl keine Propellernaben mit 6-mm-Innenloch. Da viele jedoch aus leichtem Aluminium bestehen, kann man das Innenloch durchaus mit einem Bohrer auf 6 mm erweitern. Die Befestigung an der Welle erfolgt immer per Madenschraube oder notfalls Sekundenkleber. Der Außendurchmesser der Propellernabe ist in der Regel 8 mm. Dadurch lassen sich also schon eine ganze Reihe von Rädern direkt mit einer Mutter anschrauben. &lt;br /&gt;
Die nachfolgenden Bilder zeigen, wie man sehr große Modellbauräder mit einem großen 12-mm-Loch durchaus auch sehr leicht mit Propellernabe und spezieller Modellbauradbefestigung an kleinen 5-mm- oder 6-mm-Achsen befestigt. Die Propellernaben stammen von Conrad Elektronik.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_b.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_c.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_d.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_e.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_f.jpg|center]]&lt;br /&gt;
[[Bild:achskupplungen_g.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Auf den Bildern wurden nur Muttern zur Befestigung genutzt. Bei schweren Robotern sollte die Welle durchbohrt und der mitgelieferte Splint eingesetzt werden. Dadurch wird ein Durchdrehen oder Lösen der Muttern verhindert. Ein Tropfen Sekundenkleber erreicht das Gleiche, jedoch bekommt man dies dann selbst nie mehr auseinander.&lt;br /&gt;
&lt;br /&gt;
Auf dem Bild sehen wir, das Propellernaben durchaus auch bei Motoren mit sehr kleinem Wellendurchmesser eingesetzt werden können:&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_h.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Umgehen der direkten Befestigung des Rades==&lt;br /&gt;
Man kann natürlich das Problem der Radbefestigung auch ganz einfach umgehen indem man die Räder auf einer anderen Welle / Getriebestange befestigt und die Verbindung einfach über ein Zahnriemenrad herstellt. Zahnriemenräder gibt es für viele Achsdurchmesser, die Befestigung ist oft mittels Madenschraube sehr einfach möglich. Wenn man dann noch die Räder auf einer Gewindestange statt Stahlwelle befestigt, ist das Ganze sehr einfach zu realisieren. Die Gewindestange kann man dann über Kugellager auf beiden Seiten lagern. Der Fachmann wird eine Gewindestange als Welle in der Regel nicht nutzen oder empfehlen, weil dadurch mit der Zeit die Lager beschädigt werden können und die Reibung nicht ganz optimal ist. Allerdings ist in der Praxis die Lösung durchaus für viele Dinge ausreichend und übersteht oft die übliche Lebensdauer eines Hobby-Roboters. &lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_j.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Befestigung durch Aufbohren einer Gewindestange==&lt;br /&gt;
Bei dem nachfolgenden Bild wurde ein 6-mm-Loch in eine größere Gewindestange gebohrt. Zusätzlich wurde ein kleines Loch für eine Art Madenschraube gebohrt und mit Gewinde versehen. Dadurch läßt sich die Gewindestange direkt auf die Welle aufstecken und mittels Schraube befestigen. Das Rad selbst kann wieder mit gegenläufigen Muttern angeschraubt werden. Diese Lösung ist sehr günstig, erfordert jedoch ein wenig mechanisches Geschick.&lt;br /&gt;
&lt;br /&gt;
[[Bild:achskupplungen_lukas.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
==Befestigung mit einem speziellen Felgenadapter==&lt;br /&gt;
Die recht beliebten Räder aus dem RC-Modellbaubereich (wie sie auch bei den Fotos zu den anderen Befestigungsmöglichkeiten zu sehen sind) haben an der Innenseite eine 12mm-Sechskantaufnahme. Hier lässt sich ein Adapterstück mit einem 12mm-Sechskantprofil und einer Bohrung für die Motorwelle anbringen. Dies ergibt eine stabile und kraftschlüssige Befestigung. Ein solches Adapterstück ist jedoch ohne teures Werkzeug (Fräse, Drehmaschine) nicht gerade einfach anzufertigen, da schon etliches an Präzision gefragt ist, damit die Räder nicht eiern. Es gibt jedoch mittlerweile einen Anbieter für Adapter aus Edelstahl. Die Bohrung ist 6mm groß, was auf viele Getriebemotoren passt. &lt;br /&gt;
&lt;br /&gt;
EDIT: mittlerweile sind diese Adapter dort leider nicht mehr erhältlich!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:radadapter.jpg|center|thumb|400px|Anwendungsbeispiel Radadapter]]&lt;br /&gt;
&lt;br /&gt;
==Weitere Lösungen==&lt;br /&gt;
Es gibt noch eine ganze Reihe weiterer Lösungen, wie das einfache Ankleben oder Schneiden von Außengewinde auf eine Welle. Gerne kann jeder weitere hier im Artikel erläutern. &lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Frank|Frank]] 14:40, 14. Nov 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
[[Category:Robotikeinstieg]]&lt;br /&gt;
[[Category:Praxis]]&lt;br /&gt;
[[Category:Mechanik]]&lt;/div&gt;</summary>
		<author><name>Uwegw</name></author>	</entry>

	</feed>