<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Andreasr</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Andreasr"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Andreasr"/>
	<updated>2026-04-10T21:27:58Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92514</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92514"/>
		<updated>2016-03-20T13:30:47Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Timer&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein [https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Porterweiterung_mit_SPI Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1 &amp;lt;&amp;lt; 5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
In der klassischen Steuerungstechnik ist das anzugsverzögerte und das abfallverzögerte Zeitrelais bekannt. In der SPS sind 8 (#define MAX_T 8) Timer vorhanden, die wahlweise als Einschalt- oder als Ausschaltverzögerung benutzt werden können.&amp;lt;br/&amp;gt;Das Verhalten wird durch die Operation bestimmt: &#039;&#039;opSE&#039;&#039; programmiert eine Einschaltverzögerung; &#039;&#039;opSA&#039;&#039; eine Ausschaltverzögerung.&amp;lt;br/&amp;gt;Die Zeit für die Timer wird als Vorspann zum Programm ebenfalls im EEProm abgelegt (EEDataSPSTTimer).&lt;br /&gt;
&lt;br /&gt;
Beispiel: Setze Ausgang Q1 8 sec. nachdem Eingang I1 high wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint16_t EEDataSPSTTimer[MAX_T] EEMEM = {&lt;br /&gt;
    8*(1000/PRE_TIMER),    // T1 8s&lt;br /&gt;
    ...&lt;br /&gt;
		&lt;br /&gt;
#define T1 T(0)&lt;br /&gt;
#define I1 IN(0)&lt;br /&gt;
#define Q1 OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
    LD,  I1,&lt;br /&gt;
    SE,  T1,&lt;br /&gt;
	&lt;br /&gt;
    LD,  T1,&lt;br /&gt;
    ST,  Q1,&lt;br /&gt;
    EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang programmiert werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92137</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92137"/>
		<updated>2016-02-28T22:10:49Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein [https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Porterweiterung_mit_SPI Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1 &amp;lt;&amp;lt; 5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang programmiert werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92136</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92136"/>
		<updated>2016-02-28T22:08:51Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein [https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Porterweiterung_mit_SPI Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1 &amp;lt;&amp;lt; 5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang programmiert werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=92135</id>
		<title>LPC1114 Breakout Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=92135"/>
		<updated>2016-02-28T22:02:25Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Nachdem der AVR jahrelang seine Dienste verrichtet hat, kommt man heute eigentlich nicht darum herum, auch mal über den (8-Bit) - Tellerrand zu schauen. Die ARM-CPU’s drängen sich geradezu auf und werden auch für den Bastler immer interessanter. Mittlerweile ist ein LPC1114 billiger als ein ATmega328. Und das bei einer höheren Performance und mehr verfügbarem RAM. Was mich bisher vom Einsatz abgehalten hat ist die Tatsache dass die meisten ARM Controller nur als SMD- Package (LQFP) erhältlich sind und das fehlende EEProm zum Ablegen von Konfigurationsparametern. Um diese beiden Nachteile zu eliminieren und insgesamt die Einstiegshürde für den Einsatz eines Cortex-M0 zu senken, habe ich das hier beschriebene Breakout-Board entworfen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LPC1114-Breakout.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==Features==&lt;br /&gt;
* Steckbrett-kompatibel&lt;br /&gt;
* Konfigurations-EEProm optional bestückbar (I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C)&lt;br /&gt;
* Quarz optional bestückbar&lt;br /&gt;
* Cortex 10-pin 0.05&amp;quot; JTAG/SWD Debug-Schnittstelle&lt;br /&gt;
&lt;br /&gt;
==Schaltplan==&lt;br /&gt;
[[Bild:LPC1114-Schaltplan.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Es werden im Wesentlichen alle IO-Pins des LPC auf Stiftleisten geführt. Ein Quarz und ein I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEProm sind optional bestückbar. Die Debug-Schnittstelle ist direkt mit den SWD-Pins des Prozessors verbunden.&lt;br /&gt;
{{Warnung|Der LPC1114 darf maximal mit einer Versorgungsspannung von 3,6V betrieben werden! &amp;lt;br/&amp;gt;Eine Versorgungsspannung von 5V tötet ihn!}}&lt;br /&gt;
Die Eingänge sind aber 5V-tolerant.&lt;br /&gt;
Im Anhang befinden sich die Eagle-Files. &amp;lt;br/&amp;gt;Die Fertigung der Platinen bei einem chinesischen Hersteller hat mich 16USD / 5 Platinen incl. Versand gekostet.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Im unten verlinkten Sourcecode-Paket befindet sich ein HelloLpc1114 Projekt für die LPCXpresso-IDE. Enthalten ist auch ein Treiber für das I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEprom.  Die Software ist für den Betrieb mit einem 12 MHz-Quarz konfiguriert. Die interne PLL erhöht den Takt auf 48 MHZ. Falls das Board mit dem internen RC-Oszillator oder mit einer anderen Frequenz betrieben werden soll, muss die Takt-Konfiguration angepasst werden. Dazu muss die Datei system_LPC11xx.c editiert werden. Damit man sich nicht durch die einzelnen Bit-Definitionen hangeln muss gibt es das Java-Tool [http://sourceforge.net/projects/cmsisconfig CMSIS Configurator].&lt;br /&gt;
&lt;br /&gt;
[[Bild:CMSIS-Config.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Das Projekt referenziert die CMSIS-Library CMSIS_CORE_LPC11xx. Sie ist Bestandteil des NXP LPCXpresso Installationspaketes.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Link für Nachricht an den Autor: [http://www.mikrocontroller.net/user/show/AndreasR Andreas Richter]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
[[Datei:LPC1114_Example.zip]]&lt;br /&gt;
&lt;br /&gt;
Eagle-Files:&lt;br /&gt;
[[Datei:LPC1114_Breakout_Eagle.zip]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Category:ARM]]&lt;br /&gt;
[[Category:LPC1x]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92134</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92134"/>
		<updated>2016-02-28T21:29:40Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein [https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1 &amp;lt;&amp;lt; 5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang programmiert werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92133</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92133"/>
		<updated>2016-02-28T21:27:06Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein [https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1 &amp;lt;&amp;lt; 5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92132</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92132"/>
		<updated>2016-02-28T21:24:01Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein [https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1&amp;lt;&amp;lt;5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92131</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92131"/>
		<updated>2016-02-28T20:31:22Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein |https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1&amp;lt;&amp;lt;5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92130</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92130"/>
		<updated>2016-02-28T20:30:17Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein |https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Opcode&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | attrSubBlock | attrNot | Operand | Operand | Operand | Operand | Operand | Operand&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 6 Bits Operand werden als Zahl aufgefasst und durch folgenden enum beschrieben:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum Operands	{&lt;br /&gt;
	opEnd, &lt;br /&gt;
	opStore,&lt;br /&gt;
	opSet,&lt;br /&gt;
	opReset,&lt;br /&gt;
	opLoad,&lt;br /&gt;
	opAND,&lt;br /&gt;
	opOR,&lt;br /&gt;
	opXOR,&lt;br /&gt;
	opFP,       // Flanke Positiv&lt;br /&gt;
	opFN,       // Flanke Negativ&lt;br /&gt;
&lt;br /&gt;
	opSE,       // Einschaltverz.&lt;br /&gt;
	opSA,       // Ausschaltverz.&lt;br /&gt;
	&lt;br /&gt;
	opSC,       // Set Counter&lt;br /&gt;
	opRC,       // Reset Counter&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Address-Byte ausgewertet. Das Address-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues |Address&lt;br /&gt;
 | 7 | 6 | 5| 4 | 3 | 2 | 1 | 0&lt;br /&gt;
 | Device | Device | Device | #Byte| #Byte| #Bit| #Bit| #Bit&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Die 3 Bits Device werden als Zahl aufgefasst und durch folgenden enum beschrieben: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
enum AdressTypes	{&lt;br /&gt;
	adrIn =          0&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrOut =         1&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrMerker =      2&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrSHC =         3&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrClockSwitch = 4&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrTimer =       5&amp;lt;&amp;lt;5,&lt;br /&gt;
	adrCounter =     6&amp;lt;&amp;lt;5,&lt;br /&gt;
	&lt;br /&gt;
	adrInvalid =     7&amp;lt;&amp;lt;5&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den 2 Bits #Byte können 4 aufeinanderfolgende Bytes adressiert werden.&lt;br /&gt;
Mit den 3 Bits #Bit wird das Bit im Jeweiligen Byte adressiert.&lt;br /&gt;
&lt;br /&gt;
Der Ausgang #11 hätte also folgende Adresse adrOut + Byte 1 + Bit 2 = (1&amp;lt;&amp;lt;5) + (1 &amp;lt;&amp;lt; 3) + 2&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92126</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92126"/>
		<updated>2016-02-28T17:46:11Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein |https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
[http://www.smarthomatic.org/devices/base_station.html smarthomatic]&lt;br /&gt;
&lt;br /&gt;
[http://www.fhem.de/fhem.html Home of FHEM]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
folgt...&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92125</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92125"/>
		<updated>2016-02-28T17:41:42Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein |https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Hier ist zu beachten, dass nach den Befehlen &#039;&#039;AND+KLAUF&#039;&#039; und &#039;&#039;KLZU&#039;&#039; jeweils ein Dummy-Adress Byte (0) eingefügt wird.&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung: I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung: steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absolute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch - Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit [http://fhem.de/fhem.html FHEM] lässt sich die SPS damit als intelligentes Hausautomatisierungs-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92124</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92124"/>
		<updated>2016-02-28T17:36:09Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein |https://www.mikrocontroller.net/part/ATMEGA328 ATmega328] verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann - je nach verwendeter Peripherie - die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Der ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, das der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ [https://www.mikrocontroller.net/part/UDN2981 UDN2981] angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufdioden für induktive Lasten sind integriert.&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Beim Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften bezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Kondensatoren, die mit Netzspannung beaufschlagt werden müssen X2-Typen sein! }}&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Bei der Berechnung von Teilausdrücken werden zuerst der aktuelle Operand und der Akkumulator-Inhalt auf den Stack geschoben und dann der Teilausdruck (Klammer) berechnet. Danach werden Operand und alter Akkumulator-Inhalt vom Stack zurückgeholt und mit dem Teilausdrucks-Ergebnis kombiniert. Das ganze funktioniert durch die Stack-Architektur auch rekursiv.&lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben &amp;lt;br /&amp;gt;(= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92123</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92123"/>
		<updated>2016-02-28T17:16:26Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …).&lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer [https://de.wikipedia.org/wiki/Anweisungsliste AWL]-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge, Kontroll-LED&#039;s&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten, Kontroll-LED&#039;s&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, [https://www.mikrocontroller.net/articles/RFM12 RFM12], [https://de.wikipedia.org/wiki/DCF77 DCF77] - Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale kombiniert (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit des SPS-Programms bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden, ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator. Alle Operationen werden auf Bit-Ebene durchgeführt. Der Akkumulator ist ebenfalls 1 Bit groß.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92117</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92117"/>
		<updated>2016-02-28T11:43:08Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
SPS mit Zeitschaltuhr, 230 V&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92116</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92116"/>
		<updated>2016-02-28T11:40:26Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_SHC&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92115</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92115"/>
		<updated>2016-02-28T11:40:13Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK_SWITCH&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92114</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92114"/>
		<updated>2016-02-28T11:39:58Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#ifdef WITH_CLOCK&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92113</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92113"/>
		<updated>2016-02-28T11:37:25Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RFM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92112</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92112"/>
		<updated>2016-02-28T11:36:39Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
[[Bild:ZeitSchalt1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:ZeitSchalt1.png&amp;diff=92111</id>
		<title>Datei:ZeitSchalt1.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:ZeitSchalt1.png&amp;diff=92111"/>
		<updated>2016-02-28T11:35:49Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92110</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92110"/>
		<updated>2016-02-28T11:35:13Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
=Bilder=&lt;br /&gt;
[[Bild:ZeitSchalt1.png]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230_neu.png&amp;diff=92109</id>
		<title>Datei:Eingang230 neu.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230_neu.png&amp;diff=92109"/>
		<updated>2016-02-28T11:30:54Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92108</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92108"/>
		<updated>2016-02-28T11:30:06Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230_neu.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92107</id>
		<title>Datei:Eingang230.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92107"/>
		<updated>2016-02-28T11:29:25Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Andreasr lud eine neue Version von Datei:Eingang230.png hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92106</id>
		<title>Datei:Eingang230.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92106"/>
		<updated>2016-02-28T11:28:36Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Andreasr lud eine neue Version von Datei:Eingang230.png hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92105</id>
		<title>Datei:Eingang230.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92105"/>
		<updated>2016-02-28T11:27:58Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Andreasr lud eine neue Version von Datei:Eingang230.png hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92104</id>
		<title>Datei:Eingang230.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92104"/>
		<updated>2016-02-28T11:26:12Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Andreasr lud eine neue Version von Datei:Eingang230.png hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92103</id>
		<title>Datei:Eingang230.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92103"/>
		<updated>2016-02-28T11:25:29Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Andreasr lud eine neue Version von Datei:Eingang230.png hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92102</id>
		<title>Datei:Eingang230.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92102"/>
		<updated>2016-02-28T11:25:00Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Andreasr lud eine neue Version von Datei:Eingang230.png hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92101</id>
		<title>Datei:Eingang230.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang230.png&amp;diff=92101"/>
		<updated>2016-02-28T11:22:31Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92100</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92100"/>
		<updated>2016-02-28T11:22:18Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang230.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92099</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92099"/>
		<updated>2016-02-28T11:19:03Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92098</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92098"/>
		<updated>2016-02-28T11:18:19Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Eingang.png]]&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Eingang.png&amp;diff=92097</id>
		<title>Datei:Eingang.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Eingang.png&amp;diff=92097"/>
		<updated>2016-02-28T11:17:35Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92096</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92096"/>
		<updated>2016-02-28T11:06:25Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V oder 24 V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92095</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92095"/>
		<updated>2016-02-28T11:05:57Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12V oder 24V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen [https://www.mikrocontroller.net/part/LM2574 LM2574] erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein [https://www.mikrocontroller.net/articles/RFM12 RFM12] angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3 V – 5 V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch die max. Eingangsspannung des LM2574  begrenzt - 45V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2 kOhm für 12 V und 2,2 kOhm für 24 V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100 Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92094</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92094"/>
		<updated>2016-02-28T11:00:56Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12V oder 24V Betriebsspannung&lt;br /&gt;
* Platinengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremodule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic Power Switch] Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92093</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92093"/>
		<updated>2016-02-28T10:58:12Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92092</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92092"/>
		<updated>2016-02-28T10:57:29Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
(#ifdef WITH_CLOCK)&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_CLOCK_SWITCH)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
&lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92091</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92091"/>
		<updated>2016-02-28T10:56:50Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
(#ifdef WITH_CLOCK)&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
(#ifdef WITH_CLOCK_SWITCH)&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
 &lt;br /&gt;
==smarthomatic - Potokoll==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power smarthomatic Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92090</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92090"/>
		<updated>2016-02-28T10:55:33Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
(#ifdef WITH_CLOCK)&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
(#ifdef WITH_CLOCK_SWITCH)&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
 &lt;br /&gt;
==[http://www.smarthomatic.org smarthomatic - Potokoll] ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;(#ifdef WITH_SHC)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92089</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92089"/>
		<updated>2016-02-28T10:50:52Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute &#039;&#039;attrSubBlock&#039;&#039; kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden &#039;&#039;opEnd&#039;&#039; als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
(#ifdef WITH_CLOCK)&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
(#ifdef WITH_CLOCK_SWITCH)&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
 &lt;br /&gt;
==smarthomatic - Potokoll  [http://www.smarthomatic.org] ==&lt;br /&gt;
(#ifdef WITH_SHC)&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92088</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92088"/>
		<updated>2016-02-28T10:50:03Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute attrSubBlock kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden opEnd als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
(#ifdef WITH_CLOCK)&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
(#ifdef WITH_CLOCK_SWITCH)&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
 &lt;br /&gt;
==smarthomatic - Potokoll  [http://www.smarthomatic.org] ==&lt;br /&gt;
(#ifdef WITH_SHC)&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92087</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92087"/>
		<updated>2016-02-28T10:49:29Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand Kriechstrecken etc.. einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute attrSubBlock kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden opEnd als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
(#ifdef WITH_CLOCK)&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
(#ifdef WITH_CLOCK_SWITCH)&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
 &lt;br /&gt;
==smarthomatic - Potokoll  [http://www.smarthomatic.org] ==&lt;br /&gt;
(#ifdef WITH_SHC)&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92086</id>
		<title>SPS mit ATmega</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SPS_mit_ATmega&amp;diff=92086"/>
		<updated>2016-02-28T10:47:45Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: Initial&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, &lt;br /&gt;
Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). &lt;br /&gt;
Der Nachteil einer käuflichen SPS ist der hohe Preis. &lt;br /&gt;
Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. &lt;br /&gt;
Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. &lt;br /&gt;
C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. &lt;br /&gt;
Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 oder 24V Betriebsspannung&lt;br /&gt;
* Leiterplattengröße halbes Euro-Format&lt;br /&gt;
* 8 Eingänge&lt;br /&gt;
* 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
* optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger&lt;br /&gt;
* optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, [http://http://www.smarthomatic.org/devices/power_switch.html smarthomatic] Power Switch Implementation&lt;br /&gt;
&lt;br /&gt;
=Theory of Operation=&lt;br /&gt;
Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. &lt;br /&gt;
Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. &lt;br /&gt;
Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. &lt;br /&gt;
Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. &lt;br /&gt;
Das SPS-Programm sollte für den Mikrocontroller in einem Format vorliegen, dass er leicht einlesen und interpretieren kann; ähnlich einem Maschinenprogramm für die CPU. &lt;br /&gt;
Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse.&lt;br /&gt;
Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Als Mikrocontroller wird ein ATmega328 verwendet.&lt;br /&gt;
Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine [http://www.mikrocontroller.net/articles/Erweiterung_von_digitalen_IO-Ports Porterweiterung] verwendet.&lt;br /&gt;
Die Ansteuerung der Schieberegister erfolgt per Software-SPI.&lt;br /&gt;
Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen.&lt;br /&gt;
Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt.&lt;br /&gt;
Die Spannung für den Mikrocontroller und die Peripherie wird über einen LM2574 erzeugt. Es kann je nach verwendeter Peripherie die 3,3 V oder die 5 V – Variante verwendet werden.&lt;br /&gt;
Falls z.B ein RFM12 angeschlossen werden soll empfiehlt sich die 3,3 V Variante; falls ein LCD angeschlossen werden soll die 5 V – Variante.&lt;br /&gt;
Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht.&lt;br /&gt;
Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574  begrenzt.&lt;br /&gt;
Der LM2574 hat eine max. Eingangsspannung von 45 V.&lt;br /&gt;
Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED&#039;s  ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V.&lt;br /&gt;
Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden.&lt;br /&gt;
Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.&lt;br /&gt;
&lt;br /&gt;
TODO: Eagle&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand Kriechstrecken, ... einzuhalten.}}&lt;br /&gt;
&lt;br /&gt;
Die Ausgänge werden über einen Highside-Treiber vom Typ UDN2981 angesteuert. Der Treiber besitzt TTL-kompatible Eingänge und kann bis zu 500mA schalten.&lt;br /&gt;
Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Die eigentliche Befehlsausführung ist in der Funktion &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void SPSExec(const uint8_t* prog)&amp;lt;/syntaxhighlight&amp;gt; implementiert. &lt;br /&gt;
Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
Die Operanden &#039;&#039;opLoad&#039;&#039;, &#039;&#039;opAND&#039;&#039;, &#039;&#039;opOR&#039;&#039;, &#039;&#039;opXOR&#039;&#039; können mit dem Attribute attrSubBlock kombiniert werden.&lt;br /&gt;
Das führt dazu, dass die folgenden Berechnungen bis zum Operanden opEnd als Teilausdruck aufgefasst werden,&lt;br /&gt;
der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt. &lt;br /&gt;
&lt;br /&gt;
Danach wird das Adress-Byte ausgewertet. Das Adress-Byte codiert das Device, einen Byte-Index und die Bit-Nummer:&lt;br /&gt;
&lt;br /&gt;
TODO: Grafik&lt;br /&gt;
&lt;br /&gt;
=Schreiben des SPS-Programmes=&lt;br /&gt;
Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros.&lt;br /&gt;
In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird.&lt;br /&gt;
Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
Q1 = I1 AND (I2 OR NOT I3)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define I3		IN(2)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	AND+KLAUF, 0,	// (&lt;br /&gt;
		LD, I2,&lt;br /&gt;
		OR+NOT, I3,&lt;br /&gt;
	KLZU, 0, 	// )&lt;br /&gt;
	ST,	Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define I2		IN(1)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD, 	I1,&lt;br /&gt;
	S,	Q1,	&lt;br /&gt;
	LD,	NOT+I2&lt;br /&gt;
	R,	Q1,		// dominierend Aus&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flankenerkennung steigende Flanke an I1 setzt Q1&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define I1		IN(0)&lt;br /&gt;
#define Q1		OUT(0)&lt;br /&gt;
#define Merk1		M(1)&lt;br /&gt;
&lt;br /&gt;
uint8_t EEDataSPSCode[] EEMEM= {&lt;br /&gt;
	LD,			I1,&lt;br /&gt;
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker&lt;br /&gt;
	S,			Q1,&lt;br /&gt;
	EXIT,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Compiler legt das Array  EEDataSPSCode als EEProm-File ab. &lt;br /&gt;
&lt;br /&gt;
=Timer=&lt;br /&gt;
&lt;br /&gt;
=Counter=&lt;br /&gt;
&lt;br /&gt;
=Zusatzfunktionen=&lt;br /&gt;
Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:&lt;br /&gt;
&lt;br /&gt;
==Uhr==&lt;br /&gt;
(#ifdef WITH_CLOCK)&lt;br /&gt;
Freilaufende Uhr mit DCF77-Synchronisierung.&lt;br /&gt;
&lt;br /&gt;
==Zeitschaltuhr== &lt;br /&gt;
(#ifdef WITH_CLOCK_SWITCH)&lt;br /&gt;
Zeitschaltuhr mit 8 Bits, die als Eingänge in die SPS gespiegelt werden. Zur Einstellung der Zeiten kann ein LCD und 3 Taster angeschlossen werden (Erweiterungs-Steckerleiste)&lt;br /&gt;
Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK)&lt;br /&gt;
Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.&lt;br /&gt;
 &lt;br /&gt;
==smarthomatic - Potokoll  [http://www.smarthomatic.org] ==&lt;br /&gt;
(#ifdef WITH_SHC)&lt;br /&gt;
Es wird ein [http://http://www.smarthomatic.org/devices/power_switch.html Power Switch-Device] eingebunden, das 8 Ein-/Ausgänge in die SPS spiegelt. In Verbindung mit FHEM lässt sich die SPS damit als intelligentes Hausautomatisierung-Gerät verwenden.&lt;br /&gt;
Der Source-Code von Smarthomatic wurde etwas modifiziert, da die Smarthomatic-Module normalerweise davon ausgehen, dass ihnen der ganze Mikrocontroller gehört. Die Konfiguration der Module erfolgt über ein EEProm-Konfiurations-File. Dieses musste so modifiziert werden, dass noch Platz für das SPS-Programm bleibt. Die Hardware (RTM12B) wird über die  Erweiterungs-Steckerleiste angeschlossen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Sinuswechselrichter_600W&amp;diff=92085</id>
		<title>Sinuswechselrichter 600W</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Sinuswechselrichter_600W&amp;diff=92085"/>
		<updated>2016-02-28T10:44:36Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Motivation für den Bau des Wechselrichters war der Wunsch in meiner Garage ohne Netzanschluss mal eine Schlagbohrmaschine oder andere Geräte mit Netzanschluss benutzen zu können. Auch kommt es ab und zu vor, dass man im PKW mal ein Gerät mit Netzspannung benutzen will. Gerade für Geräte mit induktiver Last (z.B. Bohrmaschine) ist es wichtig, dass die erzeugte Spannung einen möglichst sinusförmigen Verlauf hat. Die bei meinem Gerät zugrunde gelegte Leistung ist einfach die Nennleistung meiner Bohrmaschine.&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Obwohl die Schaltung mit Kleinspannung von 12 V betrieben wird, entsteht eine lebensgefährlich hohe Netzspannung von 230 V~ bzw. eine Gleichspannung von 325 V. Es sind also die Regeln für das Arbeiten mit Netzspannung genauso einzuhalten wie für eine Schaltung die direkt mit dem Stromnetz verbunden ist. Weiterhin hat die Schaltung keine galvanische Trennung zwischen Primär-und Sekundärseite (s. Kritikpunkte).  Falls die Eingangsspannung also Verbindung zum Erd- bzw. Massepotential (z.B. im Auto) hat, hat die Ausgangsspannung ebenfalls Bezug zum Massepotential. Der Sinuswandler hat also &#039;&#039;&#039;nicht&#039;&#039;&#039; die Eigenschaften eines Trenntrafos!&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist insbesondere bei Verwendung einer Autobatterie auf entsprechende Absicherung zu achten! Brandgefahr!}}&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V Eingangsspannung&lt;br /&gt;
* möglichst kompakte Bauform&lt;br /&gt;
* möglichst sinusförmige Ausgangsspannung 50 Hz&lt;br /&gt;
* geregelte Ausgangsspannung&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
&lt;br /&gt;
=Technische Details=&lt;br /&gt;
* es wird ein Zwischenkreis mit 325 V verwendet&lt;br /&gt;
* die Zwischenkreisspannung wird mittels Ferrit-Übertragers aus den 12 V herauftransformiert&lt;br /&gt;
* der Ferrit-Übertrager wird mit einer Rechteckspannung gespeist, die über eine Vollbrücke aus der Eingangsspannung erzeugt wird&lt;br /&gt;
* die Zwischenkreisspannung wird mittels Mikrocontroller über das Tastverhältnis der Rechteckspannung geregelt&lt;br /&gt;
* die Zwischenkreisspannung wird mittels Elko gepuffert, damit auch bei Geräten mit induktiver Last die Blindleistung pendeln kann&lt;br /&gt;
* aus der Zwischenkreisspannung wird über eine Vollbrücke eine PWM mit sinusförmigem Verlauf erzeugt. Nach der Filterung der PWM bleibt ein Sinus mit 50 Hz über.&lt;br /&gt;
&lt;br /&gt;
=Eingangsseite Übertrager=&lt;br /&gt;
Der Übertrager wird mit einer Rechteckwechselspannung von 40 kHz über eine Vollbrücke gespeist. Es ist sehr wichtig, dass die Rechteckspannung exakt symmetrisch ist, damit der Übertrager keine Gleichspannung „sieht“.&lt;br /&gt;
Die Symmetrie wird sichergestellt, indem ein D-Flipflop mit einer Frequenz von 80 kHz getoggelt wird.&lt;br /&gt;
Für die Regelung des Zwischenkreises wird die Rechteckspannung mit einer variablen Pulsbreite versehen. In den Pulspausen wird der Eingang des Übertragers kurzgeschlossen, indem entweder beide Eingänge auf Low oder auf High liegen. Das Steuersignal dazu ist der PWM-Ausgang des Mikrocontrollers.&lt;br /&gt;
Mit der steigenden Flanke des PWM-Signales wird FFA getoggelt. Mit der fallenden Flanke wird FFB mit dem negierten Ausgang von FFA geladen. An dessen negiertem Ausgang liegt dann also ebenfalls das Ausgangssignal von FFA. Die FF’s werden also beide mit der PWM-Frequenz getoggelt wobei die Phasenverschiebung der FF’s der t&amp;lt;small&amp;gt;&amp;lt;sub&amp;gt;Ein&amp;lt;/sub&amp;gt;&amp;lt;/small&amp;gt; – Zeit der PWM entspricht:&lt;br /&gt;
* langes t&amp;lt;small&amp;gt;&amp;lt;sub&amp;gt;Ein&amp;lt;/sub&amp;gt;&amp;lt;/small&amp;gt;: große Phasenverschiebung; Brücke lange gegenphasig; viel Energie wird eingespeist&lt;br /&gt;
* kurzes t&amp;lt;small&amp;gt;&amp;lt;sub&amp;gt;Ein&amp;lt;/sub&amp;gt;&amp;lt;/small&amp;gt;: kleine Phasenverschiebung; Brücke kurz gegenphasig; wenig Energie wird eingespeist&lt;br /&gt;
&lt;br /&gt;
[[Bild:InputLogic.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die PWM wird mittels einer PID-Regelung in Software geregelt. &amp;lt;br /&amp;gt;&lt;br /&gt;
Die Eingangsgröße dafür ist die Zwischenkeisspannung, die möglichst genau 325 V (&amp;lt;math&amp;gt;230 V*\sqrt{2}&amp;lt;/math&amp;gt;) betragen soll.&lt;br /&gt;
&lt;br /&gt;
=Ausgang Sinus-Brücke=&lt;br /&gt;
Die Zwischenkreisspannung wird über eine zweite Vollbrücke in eine Sinusspannung mit 50 Hz gewandelt. Dazu muss eine PWM erzeugt werden, deren Pulsbreite einem Sinussignal folgt. Da das PWM-Signal auch in der Ausgangsspannung enthalten ist, muss die Ausgangsspannung am Ende noch gefiltert werden. Das erfolgt über ein LC-Glied. Je größer die PWM-Frequenz ist, desto einfacher kann das PWM-Signal herausgefiltert werden (kleinere Induktivität, kleinerer Kondensator). Mit dem verwendeten ATmega ist eine PWM von 20kHz bei 20 MHz Taktfrequenz ein guter Kompromiss. Es bleiben dann 1000 Schritte für das Sinussignal.&lt;br /&gt;
Nach jeder Halbwelle (10 ms; 200 Schritte bei 20 kHz) muss die Brücke umgepolt werden.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Ziel war es, möglichst günstige und einfach zu beschaffende Bauteile zu verwenden. Die Vollbrücken werden über jeweils 2 Treiber [http://www.mikrocontroller.net/part/IR2184 IR2184] gesteuert. Dieser Treiber hat eine eingebaute Deadtime von 500 ns zwischen den Umschaltvorgängen. Als Brückentransistoren werden N-Kanal MOSFETS verwendet.&lt;br /&gt;
Die gesamte Steuerung wird über einen ATmega88 realisiert.&lt;br /&gt;
&lt;br /&gt;
===Eingang===&lt;br /&gt;
Eingangsseitig wir als Brückentransistor der [http://www.mikrocontroller.net/part/IRF1404 IRF1404] verwendet.  Er ist mit einem R&amp;lt;sub&amp;gt;DS(on)&amp;lt;/sub&amp;gt; vom 4mΩ und Maximalstrom von 202 A spezifiziert. Wobei die Beinchen des TO220 Gehäuses diesen Strom nicht lange aushalten dürften.  Bei einer Nennleistung von 600 W und 12 V Eingangsspannung müssen die Transistoren dauerhaft 25 A aushalten können  (600 W / 12 V / 2). Wichtig ist hier ein entsprechendes Design der Zuleitungen und Anschlüsse. Ich habe das mit kleinen Stromschienen aus 1 mm Kupferblech realisiert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:InputTransistor.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Die Eingangsspannung muss mit Stützkondensatoren gepuffert werden, da sonst die Spannung während der Schaltvorgänge durch die Induktivität der Zuleitungen einbricht und dadurch Potentialverschiebungen entstehen können, die Brückentransistoren und Treiber zerstören.&lt;br /&gt;
&lt;br /&gt;
[[Bild:InputElkos.png|200px]]    [[Bild:InputKerkos.png|100px]] &lt;br /&gt;
&amp;lt;br /&amp;gt; Aktuell werden 3 Elkos á 1000 µF und 8 Kerkos á 100 nF verwendet.&lt;br /&gt;
Ich fürchte, diese sind zu niedrig dimensioniert, bzw. werden auf Dauer den Ripplestrom nicht aushalten können (Kritikpunkte).&lt;br /&gt;
&lt;br /&gt;
===Übertrager===&lt;br /&gt;
Mit dem Berechnungsprogramm auf&lt;br /&gt;
[http://schmidt-walter.eit.h-da.de/smps/vgw_smps.html schmidt-walter.eit.h-da.de/smps/vgw_smps.html]&lt;br /&gt;
wurde folgendes ermittelt:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Berechnung1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
Als Zwischenkreisspannung wurde hier 350 V zugrunde gelegt, damit noch etwas Reserve zum Regeln bleibt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Berechnung2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Es wird ein Übertrager vom Typ ETD59 verwendet. Die Primärwicklung hat 2 Windungen, die Sekundärwicklung hat 74 Windungen.&lt;br /&gt;
Als Material für die Primärwindung dient 0,85 mm Cu-Lackdraht. Dieser hat einen Querschnitt von 0,56 mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;. Bei einer empfohlenen Stromdichte für Trafowicklungen von 3 A/mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; braucht man also ungefähr 30 Drähte parallel für 50 A. Es hat sich als praktisch erwiesen, für die Einzeldrähte eher einen kleinen Drahtdurchmesser zu wählen (&amp;lt; 1 mm). Dadurch hat man fast so etwas wie Litze. Das lässt sich einfacher wickeln (auch 2 Windungen können schwierig sein!).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Primaer.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Sekundärseitig wurde ein Cu-Lackdraht von 1 mm Durchmesser verwendet; das entspricht einem Querschnitt von 0,78 mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;. Damit kommt man bei einem Strom von 2 A auf eine Stromdichte von 2,54 A/mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sekundaer.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Zwischen die 2 Lagen der Sekundärwicklung wurde eine Isolierung aus Mylarfolie gewickelt da erhebliche Spannungsunterschiede zwischen den Lagen bestehen. Der Lack des Drahtes würde hier früher oder später durchschlagen. Zwischen Sekundär-und Primärwicklung befindet sich ebenfalls eine Isolierung aus mehreren Lagen Folie.&lt;br /&gt;
&lt;br /&gt;
===Spannungsmessung===&lt;br /&gt;
Der ATmega misst die Eingangsspannung und die Zwischenkreisspannung über entsprechende Spannungsteiler.&lt;br /&gt;
&lt;br /&gt;
===Stommessung===&lt;br /&gt;
Der ATmega misst den Eingangsstrom und den Gleichstrom im Zwischenkreis über Shunts im Masse-Zweig. Die Messspannung wird über einen OPV, der als Differenzverstärker arbeitet, verstärkt. Die negative Versorgungsspannung für die OPV’s wird mit einer Ladungspumpe erzeugt. &lt;br /&gt;
Als Shunt dient ein Konstantandraht von 0,5 mm Durchmesser. Im Primärkreis werden 30 Abschnitte von 1 cm parallelgeschaltet:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Shunt1.png|200px]]&lt;br /&gt;
&lt;br /&gt;
===Zwischenkreis===&lt;br /&gt;
Die Sekundärspannung wird mit schnellen Siliziumdioden (40 kHz) gleichgerichtet, an einer Drossel geglättet und auf  Elkos mit einer Gesamtkapazität von 440 µF gespeist. Diese puffern die Zwischenkreisspannung.&lt;br /&gt;
Parallel zu den Elkos befinden sich noch ein Folienkondensator und 4 Keramikkondensatoren dicht an den MOSFETS. Ohne diese kam es zu erheblichen EMV-Problemen wenn die Ausgangsstufe eingeschaltet wurde. Die Störungen schlugen bis in den Primärkreis durch und führten z.B. dazu dass der µC sporadisch abstürzte.&lt;br /&gt;
&lt;br /&gt;
===Ausgangsschaltung===&lt;br /&gt;
Es wird eine Vollbrücke bestehend aus 4 MOSFETS [http://www.mikrocontroller.net/part/IRFP450 IRFP 450] verwendet. V&amp;lt;sub&amp;gt;DDS&amp;lt;/sub&amp;gt; ist mit 500 V angegeben. Vom Controller werden 2 Signale geliefert: Sinus-PWM und Polarität. Diese Signale werden durch eine Logikschaltung verknüpft. &amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:OutputLogic.png|400px]]&lt;br /&gt;
&amp;lt;br /&amp;gt;Eine Brücke ist fest auf Low und die andere gibt das PWM-Signal aus. Beim Wechsel des Polaritätssignales kehrt sich die Funktion der Brücken um. Die erzeugte Sinus-PWM wird über 2 Drosseln und einen Kondensator gefiltert.&lt;br /&gt;
Die Drosseln machten hier einige Probleme (Erwärmung des Kerns).  Durch ein Kernmaterial höherer Güte (Farbe Grau) und einen kleinen Lüfter :-( konnte ich die Erwärmung in den Griff bekommen.&lt;br /&gt;
&lt;br /&gt;
=Aufbau=&lt;br /&gt;
Ein erster Aufbau auf Lochraster zeigte ziemliche EMV-Probleme. Besonders das Einschalten des Ausgangskreises erzeugte massiv Störungen auf der Eingangsseite und auch auf der Spannungsversorgung des µC.  Deshalb entschloss ich mich, Platinen ätzen zu lassen. Die Schaltung ist in den Leistungs- und in den Controllerteil unterteilt. Beide sind mittels eines kurzen Flachbandkabels verbunden. Durch meine EAGLE-Lizenz ist die Platinengröße auf Euroformat begrenzt, was ziemlich knapp für die Leistungsseite ist. Den hohen Strom in der Eingangsseite leite ich über „Stromschienen“ aus 1 mm Kupferblech, welche auf die Platine montiert sind. Dafür habe ich eigens Eagle-Bauteile definiert. So werden auch die Transistoren im Eingangskreis mit einem entsprechenden Kupferquerschnitt versorgt.&lt;br /&gt;
Die Leistungstransistoren sind zur Kühlung mit dem Alu-Gehäuse verbunden. Es ist zu beachten, dass die Drain-Anschlüsse intern mit den Kühlfahnen verbunden sind. Entsprechende Isolierungen aus Glimmerfolie (ggf. doppelt für die 230 V-Seite) sind unbedingt notwendig!&lt;br /&gt;
&lt;br /&gt;
=Bedienung=&lt;br /&gt;
Der WR wird über ein 3-Tasten-Menü eingestellt. Ein LCD dient der Ausgabe wichtiger Parameter.&lt;br /&gt;
Man kann eine Begrenzung des Eingangsstromes einstellen, damit der WR z.B. an einer mit nur 20 A abgesicherten Steckdose im Auto betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Als Controller kommt wie gesagt ein ATmega88 mit 20 MHz Clock zum Einsatz.&lt;br /&gt;
Die Software ist in C / C++ geschrieben. Bei der Implementierung der Menü-Funktionen erleichtert die Verwendung von Klassen, Vererbung und virtuellen Methoden die Arbeit sehr. Wenn man es mit der Verwendung von C++ - Features nicht übertreibt (keine STL-Klassen!), bleibt der erzeugte Code sehr kompakt - aktuell findet das Programm immer noch in einen ATmega88 Platz! Als Entwicklungsumgebung kommt Atmel Studio zum Einsatz.&lt;br /&gt;
&amp;lt;br /&amp;gt;Timer0 erzeugt eine 8-Bit PWM für die Eingangsbrücke. &amp;lt;br /&amp;gt;&lt;br /&gt;
Timer1 ist für die 16-Bit Sinus-PWM der Ausgangs-Brücke zuständig. Die Zwischenkreisspannung wird über eine PID-Regelung konstant gehalten, die die PWM für die Eingangsbrücke beeinflusst. Die Regler-Parameter wurden aus der Sprungantwort ermittelt und empirisch optimiert. Eine gute Erklärung findet sich hier:&lt;br /&gt;
[http://rn-wissen.de/wiki/index.php/Regelungstechnik rn-wissen.de/wiki/index.php/Regelungstechnik]&lt;br /&gt;
Es werden periodisch 4 Analogwerte mit verschiedenen Abtastraten gemessen: Zwischenkreisspannung, Eingangsspannung, Eingangsstrom, Zwischenkreisstrom. Die Zwischenkreisspannung wird mit der höchsten Abtastrate von 2 ms gemessen. Entsprechend läuft die Regelschleife im 2 ms- Zyklus.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Sinus-Werte wurden mit Excel berechnet und werden als Tabelle in die Software includiert (eine Halbwelle). Der ATmega hat die &amp;quot;Besonderheit&amp;quot;, dass auch beim PWM-Registerwert von 0 ein kurzer Spike ausgegeben wird. Um das zu verhindern, wird die PWM invertiert betrieben: der Max.-Wert stellt das Low-Signal dar. In Excel werden die Werte gleich entsprechend berechnet, so dass der Controller die Werte direkt verwenden kann.  In jedem Timer1-Overflow-Interrupt wird der nächste Wert aus der Sinustabelle ins PWM-Register geladen. Nachdem eine komplette Halbwelle ausgegeben wurde erfolgt die Polaritätsumschaltung über einen Controller-Pin der auf die Treiberlogik wirkt.&lt;br /&gt;
&lt;br /&gt;
=Tests=&lt;br /&gt;
Zum Testen der Funktion ist ein Oszilloskop von großem Vorteil. Insbesondere der Signalverlauf an den Gates für die Brückentransistoren muss sauber sein; sonst ist ein früher Tod der Leistungshalbleiter sehr wahrscheinlich. Ich habe mir selbst einige IRF1404 zerstört weil ein Gate unbemerkt offen war. Zum Messen habe ich die Schaltung mit einer ohmschen Last von 150 W betrieben (gut wenn man noch ein paar Glühbirnen in der Schublade hat :-)). Als Spannungsquelle diente ein PC-Netzteil  (12 V). Als alles sauber lief (verzerrungsfreier Sinus auf Oszilloskop) habe ich meine Bohrmaschine über Autobatterie angeschlossen - Funktioniert!&lt;br /&gt;
&lt;br /&gt;
=Kritikpunkte / Verbesserungsvorschläge=&lt;br /&gt;
&lt;br /&gt;
* Galvanische Verbindung Eingang Ausgang&lt;br /&gt;
* Eingangselkos evtl. zu klein dimensioniert; Rippleströme?&lt;br /&gt;
* Spannungsfestigkeit Treiber IR2184: Zwischen den Pins 5 und 6 liegt die volle Netzspannung an. Die Mindestkriechstrecke wird nicht eingehalten! Abhilfe: anderer Treiber mit anderem PIN-Layout?&lt;br /&gt;
* EMV-Probleme beim Einschalten des Ausgangstreibers. Bessere Abblockung der Zwischenkreisspannung? Evtl. würde auch eine Verbesserung durch die galvan. Trennung (Punkt 1) erreicht.&lt;br /&gt;
* Messung Wechselspannung/-Strom, Berechnung Wirkungsgrad, cosinus phi&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
&lt;br /&gt;
[http://www.roboternetz.de/community/threads/30495-Projekt-Sinuswechselrichter-12V-230V roboternetz.de Sinuswechselrichter-12V-230V]&lt;br /&gt;
&lt;br /&gt;
[http://www.avr-asm-download.de/praesentation/Teil_8_Beispiel_11.pdf Ein Sinusgenerator mit AVR-Timer]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
[[Datei:Source_Sinuswandler.zip]]&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
[[Datei:Eagle_Sinuswandler.zip]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sinuswechselrichter1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sinuswechselrichter2.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Link für Nachricht an den Autor: [http://www.mikrocontroller.net/user/show/AndreasR Andreas Richter]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Sinuswechselrichter_600W&amp;diff=92084</id>
		<title>Sinuswechselrichter 600W</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Sinuswechselrichter_600W&amp;diff=92084"/>
		<updated>2016-02-28T10:43:59Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von andreasr&#039;&#039;&lt;br /&gt;
Die Motivation für den Bau des Wechselrichters war der Wunsch in meiner Garage ohne Netzanschluss mal eine Schlagbohrmaschine oder andere Geräte mit Netzanschluss benutzen zu können. Auch kommt es ab und zu vor, dass man im PKW mal ein Gerät mit Netzspannung benutzen will. Gerade für Geräte mit induktiver Last (z.B. Bohrmaschine) ist es wichtig, dass die erzeugte Spannung einen möglichst sinusförmigen Verlauf hat. Die bei meinem Gerät zugrunde gelegte Leistung ist einfach die Nennleistung meiner Bohrmaschine.&lt;br /&gt;
&lt;br /&gt;
=Sicherheitshinweis=&lt;br /&gt;
{{Warnung|Obwohl die Schaltung mit Kleinspannung von 12 V betrieben wird, entsteht eine lebensgefährlich hohe Netzspannung von 230 V~ bzw. eine Gleichspannung von 325 V. Es sind also die Regeln für das Arbeiten mit Netzspannung genauso einzuhalten wie für eine Schaltung die direkt mit dem Stromnetz verbunden ist. Weiterhin hat die Schaltung keine galvanische Trennung zwischen Primär-und Sekundärseite (s. Kritikpunkte).  Falls die Eingangsspannung also Verbindung zum Erd- bzw. Massepotential (z.B. im Auto) hat, hat die Ausgangsspannung ebenfalls Bezug zum Massepotential. Der Sinuswandler hat also &#039;&#039;&#039;nicht&#039;&#039;&#039; die Eigenschaften eines Trenntrafos!&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist insbesondere bei Verwendung einer Autobatterie auf entsprechende Absicherung zu achten! Brandgefahr!}}&lt;br /&gt;
&lt;br /&gt;
=Features=&lt;br /&gt;
* 12 V Eingangsspannung&lt;br /&gt;
* möglichst kompakte Bauform&lt;br /&gt;
* möglichst sinusförmige Ausgangsspannung 50 Hz&lt;br /&gt;
* geregelte Ausgangsspannung&lt;br /&gt;
* möglichst preiswerte und einfach zu beschaffende Komponenten&lt;br /&gt;
&lt;br /&gt;
=Technische Details=&lt;br /&gt;
* es wird ein Zwischenkreis mit 325 V verwendet&lt;br /&gt;
* die Zwischenkreisspannung wird mittels Ferrit-Übertragers aus den 12 V herauftransformiert&lt;br /&gt;
* der Ferrit-Übertrager wird mit einer Rechteckspannung gespeist, die über eine Vollbrücke aus der Eingangsspannung erzeugt wird&lt;br /&gt;
* die Zwischenkreisspannung wird mittels Mikrocontroller über das Tastverhältnis der Rechteckspannung geregelt&lt;br /&gt;
* die Zwischenkreisspannung wird mittels Elko gepuffert, damit auch bei Geräten mit induktiver Last die Blindleistung pendeln kann&lt;br /&gt;
* aus der Zwischenkreisspannung wird über eine Vollbrücke eine PWM mit sinusförmigem Verlauf erzeugt. Nach der Filterung der PWM bleibt ein Sinus mit 50 Hz über.&lt;br /&gt;
&lt;br /&gt;
=Eingangsseite Übertrager=&lt;br /&gt;
Der Übertrager wird mit einer Rechteckwechselspannung von 40 kHz über eine Vollbrücke gespeist. Es ist sehr wichtig, dass die Rechteckspannung exakt symmetrisch ist, damit der Übertrager keine Gleichspannung „sieht“.&lt;br /&gt;
Die Symmetrie wird sichergestellt, indem ein D-Flipflop mit einer Frequenz von 80 kHz getoggelt wird.&lt;br /&gt;
Für die Regelung des Zwischenkreises wird die Rechteckspannung mit einer variablen Pulsbreite versehen. In den Pulspausen wird der Eingang des Übertragers kurzgeschlossen, indem entweder beide Eingänge auf Low oder auf High liegen. Das Steuersignal dazu ist der PWM-Ausgang des Mikrocontrollers.&lt;br /&gt;
Mit der steigenden Flanke des PWM-Signales wird FFA getoggelt. Mit der fallenden Flanke wird FFB mit dem negierten Ausgang von FFA geladen. An dessen negiertem Ausgang liegt dann also ebenfalls das Ausgangssignal von FFA. Die FF’s werden also beide mit der PWM-Frequenz getoggelt wobei die Phasenverschiebung der FF’s der t&amp;lt;small&amp;gt;&amp;lt;sub&amp;gt;Ein&amp;lt;/sub&amp;gt;&amp;lt;/small&amp;gt; – Zeit der PWM entspricht:&lt;br /&gt;
* langes t&amp;lt;small&amp;gt;&amp;lt;sub&amp;gt;Ein&amp;lt;/sub&amp;gt;&amp;lt;/small&amp;gt;: große Phasenverschiebung; Brücke lange gegenphasig; viel Energie wird eingespeist&lt;br /&gt;
* kurzes t&amp;lt;small&amp;gt;&amp;lt;sub&amp;gt;Ein&amp;lt;/sub&amp;gt;&amp;lt;/small&amp;gt;: kleine Phasenverschiebung; Brücke kurz gegenphasig; wenig Energie wird eingespeist&lt;br /&gt;
&lt;br /&gt;
[[Bild:InputLogic.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die PWM wird mittels einer PID-Regelung in Software geregelt. &amp;lt;br /&amp;gt;&lt;br /&gt;
Die Eingangsgröße dafür ist die Zwischenkeisspannung, die möglichst genau 325 V (&amp;lt;math&amp;gt;230 V*\sqrt{2}&amp;lt;/math&amp;gt;) betragen soll.&lt;br /&gt;
&lt;br /&gt;
=Ausgang Sinus-Brücke=&lt;br /&gt;
Die Zwischenkreisspannung wird über eine zweite Vollbrücke in eine Sinusspannung mit 50 Hz gewandelt. Dazu muss eine PWM erzeugt werden, deren Pulsbreite einem Sinussignal folgt. Da das PWM-Signal auch in der Ausgangsspannung enthalten ist, muss die Ausgangsspannung am Ende noch gefiltert werden. Das erfolgt über ein LC-Glied. Je größer die PWM-Frequenz ist, desto einfacher kann das PWM-Signal herausgefiltert werden (kleinere Induktivität, kleinerer Kondensator). Mit dem verwendeten ATmega ist eine PWM von 20kHz bei 20 MHz Taktfrequenz ein guter Kompromiss. Es bleiben dann 1000 Schritte für das Sinussignal.&lt;br /&gt;
Nach jeder Halbwelle (10 ms; 200 Schritte bei 20 kHz) muss die Brücke umgepolt werden.&lt;br /&gt;
&lt;br /&gt;
=Hardware=&lt;br /&gt;
Ziel war es, möglichst günstige und einfach zu beschaffende Bauteile zu verwenden. Die Vollbrücken werden über jeweils 2 Treiber [http://www.mikrocontroller.net/part/IR2184 IR2184] gesteuert. Dieser Treiber hat eine eingebaute Deadtime von 500 ns zwischen den Umschaltvorgängen. Als Brückentransistoren werden N-Kanal MOSFETS verwendet.&lt;br /&gt;
Die gesamte Steuerung wird über einen ATmega88 realisiert.&lt;br /&gt;
&lt;br /&gt;
===Eingang===&lt;br /&gt;
Eingangsseitig wir als Brückentransistor der [http://www.mikrocontroller.net/part/IRF1404 IRF1404] verwendet.  Er ist mit einem R&amp;lt;sub&amp;gt;DS(on)&amp;lt;/sub&amp;gt; vom 4mΩ und Maximalstrom von 202 A spezifiziert. Wobei die Beinchen des TO220 Gehäuses diesen Strom nicht lange aushalten dürften.  Bei einer Nennleistung von 600 W und 12 V Eingangsspannung müssen die Transistoren dauerhaft 25 A aushalten können  (600 W / 12 V / 2). Wichtig ist hier ein entsprechendes Design der Zuleitungen und Anschlüsse. Ich habe das mit kleinen Stromschienen aus 1 mm Kupferblech realisiert.&lt;br /&gt;
&lt;br /&gt;
[[Bild:InputTransistor.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Die Eingangsspannung muss mit Stützkondensatoren gepuffert werden, da sonst die Spannung während der Schaltvorgänge durch die Induktivität der Zuleitungen einbricht und dadurch Potentialverschiebungen entstehen können, die Brückentransistoren und Treiber zerstören.&lt;br /&gt;
&lt;br /&gt;
[[Bild:InputElkos.png|200px]]    [[Bild:InputKerkos.png|100px]] &lt;br /&gt;
&amp;lt;br /&amp;gt; Aktuell werden 3 Elkos á 1000 µF und 8 Kerkos á 100 nF verwendet.&lt;br /&gt;
Ich fürchte, diese sind zu niedrig dimensioniert, bzw. werden auf Dauer den Ripplestrom nicht aushalten können (Kritikpunkte).&lt;br /&gt;
&lt;br /&gt;
===Übertrager===&lt;br /&gt;
Mit dem Berechnungsprogramm auf&lt;br /&gt;
[http://schmidt-walter.eit.h-da.de/smps/vgw_smps.html schmidt-walter.eit.h-da.de/smps/vgw_smps.html]&lt;br /&gt;
wurde folgendes ermittelt:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Berechnung1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
Als Zwischenkreisspannung wurde hier 350 V zugrunde gelegt, damit noch etwas Reserve zum Regeln bleibt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Berechnung2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Es wird ein Übertrager vom Typ ETD59 verwendet. Die Primärwicklung hat 2 Windungen, die Sekundärwicklung hat 74 Windungen.&lt;br /&gt;
Als Material für die Primärwindung dient 0,85 mm Cu-Lackdraht. Dieser hat einen Querschnitt von 0,56 mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;. Bei einer empfohlenen Stromdichte für Trafowicklungen von 3 A/mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; braucht man also ungefähr 30 Drähte parallel für 50 A. Es hat sich als praktisch erwiesen, für die Einzeldrähte eher einen kleinen Drahtdurchmesser zu wählen (&amp;lt; 1 mm). Dadurch hat man fast so etwas wie Litze. Das lässt sich einfacher wickeln (auch 2 Windungen können schwierig sein!).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Primaer.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Sekundärseitig wurde ein Cu-Lackdraht von 1 mm Durchmesser verwendet; das entspricht einem Querschnitt von 0,78 mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;. Damit kommt man bei einem Strom von 2 A auf eine Stromdichte von 2,54 A/mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sekundaer.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Zwischen die 2 Lagen der Sekundärwicklung wurde eine Isolierung aus Mylarfolie gewickelt da erhebliche Spannungsunterschiede zwischen den Lagen bestehen. Der Lack des Drahtes würde hier früher oder später durchschlagen. Zwischen Sekundär-und Primärwicklung befindet sich ebenfalls eine Isolierung aus mehreren Lagen Folie.&lt;br /&gt;
&lt;br /&gt;
===Spannungsmessung===&lt;br /&gt;
Der ATmega misst die Eingangsspannung und die Zwischenkreisspannung über entsprechende Spannungsteiler.&lt;br /&gt;
&lt;br /&gt;
===Stommessung===&lt;br /&gt;
Der ATmega misst den Eingangsstrom und den Gleichstrom im Zwischenkreis über Shunts im Masse-Zweig. Die Messspannung wird über einen OPV, der als Differenzverstärker arbeitet, verstärkt. Die negative Versorgungsspannung für die OPV’s wird mit einer Ladungspumpe erzeugt. &lt;br /&gt;
Als Shunt dient ein Konstantandraht von 0,5 mm Durchmesser. Im Primärkreis werden 30 Abschnitte von 1 cm parallelgeschaltet:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Shunt1.png|200px]]&lt;br /&gt;
&lt;br /&gt;
===Zwischenkreis===&lt;br /&gt;
Die Sekundärspannung wird mit schnellen Siliziumdioden (40 kHz) gleichgerichtet, an einer Drossel geglättet und auf  Elkos mit einer Gesamtkapazität von 440 µF gespeist. Diese puffern die Zwischenkreisspannung.&lt;br /&gt;
Parallel zu den Elkos befinden sich noch ein Folienkondensator und 4 Keramikkondensatoren dicht an den MOSFETS. Ohne diese kam es zu erheblichen EMV-Problemen wenn die Ausgangsstufe eingeschaltet wurde. Die Störungen schlugen bis in den Primärkreis durch und führten z.B. dazu dass der µC sporadisch abstürzte.&lt;br /&gt;
&lt;br /&gt;
===Ausgangsschaltung===&lt;br /&gt;
Es wird eine Vollbrücke bestehend aus 4 MOSFETS [http://www.mikrocontroller.net/part/IRFP450 IRFP 450] verwendet. V&amp;lt;sub&amp;gt;DDS&amp;lt;/sub&amp;gt; ist mit 500 V angegeben. Vom Controller werden 2 Signale geliefert: Sinus-PWM und Polarität. Diese Signale werden durch eine Logikschaltung verknüpft. &amp;lt;br /&amp;gt;&lt;br /&gt;
[[Bild:OutputLogic.png|400px]]&lt;br /&gt;
&amp;lt;br /&amp;gt;Eine Brücke ist fest auf Low und die andere gibt das PWM-Signal aus. Beim Wechsel des Polaritätssignales kehrt sich die Funktion der Brücken um. Die erzeugte Sinus-PWM wird über 2 Drosseln und einen Kondensator gefiltert.&lt;br /&gt;
Die Drosseln machten hier einige Probleme (Erwärmung des Kerns).  Durch ein Kernmaterial höherer Güte (Farbe Grau) und einen kleinen Lüfter :-( konnte ich die Erwärmung in den Griff bekommen.&lt;br /&gt;
&lt;br /&gt;
=Aufbau=&lt;br /&gt;
Ein erster Aufbau auf Lochraster zeigte ziemliche EMV-Probleme. Besonders das Einschalten des Ausgangskreises erzeugte massiv Störungen auf der Eingangsseite und auch auf der Spannungsversorgung des µC.  Deshalb entschloss ich mich, Platinen ätzen zu lassen. Die Schaltung ist in den Leistungs- und in den Controllerteil unterteilt. Beide sind mittels eines kurzen Flachbandkabels verbunden. Durch meine EAGLE-Lizenz ist die Platinengröße auf Euroformat begrenzt, was ziemlich knapp für die Leistungsseite ist. Den hohen Strom in der Eingangsseite leite ich über „Stromschienen“ aus 1 mm Kupferblech, welche auf die Platine montiert sind. Dafür habe ich eigens Eagle-Bauteile definiert. So werden auch die Transistoren im Eingangskreis mit einem entsprechenden Kupferquerschnitt versorgt.&lt;br /&gt;
Die Leistungstransistoren sind zur Kühlung mit dem Alu-Gehäuse verbunden. Es ist zu beachten, dass die Drain-Anschlüsse intern mit den Kühlfahnen verbunden sind. Entsprechende Isolierungen aus Glimmerfolie (ggf. doppelt für die 230 V-Seite) sind unbedingt notwendig!&lt;br /&gt;
&lt;br /&gt;
=Bedienung=&lt;br /&gt;
Der WR wird über ein 3-Tasten-Menü eingestellt. Ein LCD dient der Ausgabe wichtiger Parameter.&lt;br /&gt;
Man kann eine Begrenzung des Eingangsstromes einstellen, damit der WR z.B. an einer mit nur 20 A abgesicherten Steckdose im Auto betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
=Software=&lt;br /&gt;
Als Controller kommt wie gesagt ein ATmega88 mit 20 MHz Clock zum Einsatz.&lt;br /&gt;
Die Software ist in C / C++ geschrieben. Bei der Implementierung der Menü-Funktionen erleichtert die Verwendung von Klassen, Vererbung und virtuellen Methoden die Arbeit sehr. Wenn man es mit der Verwendung von C++ - Features nicht übertreibt (keine STL-Klassen!), bleibt der erzeugte Code sehr kompakt - aktuell findet das Programm immer noch in einen ATmega88 Platz! Als Entwicklungsumgebung kommt Atmel Studio zum Einsatz.&lt;br /&gt;
&amp;lt;br /&amp;gt;Timer0 erzeugt eine 8-Bit PWM für die Eingangsbrücke. &amp;lt;br /&amp;gt;&lt;br /&gt;
Timer1 ist für die 16-Bit Sinus-PWM der Ausgangs-Brücke zuständig. Die Zwischenkreisspannung wird über eine PID-Regelung konstant gehalten, die die PWM für die Eingangsbrücke beeinflusst. Die Regler-Parameter wurden aus der Sprungantwort ermittelt und empirisch optimiert. Eine gute Erklärung findet sich hier:&lt;br /&gt;
[http://rn-wissen.de/wiki/index.php/Regelungstechnik rn-wissen.de/wiki/index.php/Regelungstechnik]&lt;br /&gt;
Es werden periodisch 4 Analogwerte mit verschiedenen Abtastraten gemessen: Zwischenkreisspannung, Eingangsspannung, Eingangsstrom, Zwischenkreisstrom. Die Zwischenkreisspannung wird mit der höchsten Abtastrate von 2 ms gemessen. Entsprechend läuft die Regelschleife im 2 ms- Zyklus.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Sinus-Werte wurden mit Excel berechnet und werden als Tabelle in die Software includiert (eine Halbwelle). Der ATmega hat die &amp;quot;Besonderheit&amp;quot;, dass auch beim PWM-Registerwert von 0 ein kurzer Spike ausgegeben wird. Um das zu verhindern, wird die PWM invertiert betrieben: der Max.-Wert stellt das Low-Signal dar. In Excel werden die Werte gleich entsprechend berechnet, so dass der Controller die Werte direkt verwenden kann.  In jedem Timer1-Overflow-Interrupt wird der nächste Wert aus der Sinustabelle ins PWM-Register geladen. Nachdem eine komplette Halbwelle ausgegeben wurde erfolgt die Polaritätsumschaltung über einen Controller-Pin der auf die Treiberlogik wirkt.&lt;br /&gt;
&lt;br /&gt;
=Tests=&lt;br /&gt;
Zum Testen der Funktion ist ein Oszilloskop von großem Vorteil. Insbesondere der Signalverlauf an den Gates für die Brückentransistoren muss sauber sein; sonst ist ein früher Tod der Leistungshalbleiter sehr wahrscheinlich. Ich habe mir selbst einige IRF1404 zerstört weil ein Gate unbemerkt offen war. Zum Messen habe ich die Schaltung mit einer ohmschen Last von 150 W betrieben (gut wenn man noch ein paar Glühbirnen in der Schublade hat :-)). Als Spannungsquelle diente ein PC-Netzteil  (12 V). Als alles sauber lief (verzerrungsfreier Sinus auf Oszilloskop) habe ich meine Bohrmaschine über Autobatterie angeschlossen - Funktioniert!&lt;br /&gt;
&lt;br /&gt;
=Kritikpunkte / Verbesserungsvorschläge=&lt;br /&gt;
&lt;br /&gt;
* Galvanische Verbindung Eingang Ausgang&lt;br /&gt;
* Eingangselkos evtl. zu klein dimensioniert; Rippleströme?&lt;br /&gt;
* Spannungsfestigkeit Treiber IR2184: Zwischen den Pins 5 und 6 liegt die volle Netzspannung an. Die Mindestkriechstrecke wird nicht eingehalten! Abhilfe: anderer Treiber mit anderem PIN-Layout?&lt;br /&gt;
* EMV-Probleme beim Einschalten des Ausgangstreibers. Bessere Abblockung der Zwischenkreisspannung? Evtl. würde auch eine Verbesserung durch die galvan. Trennung (Punkt 1) erreicht.&lt;br /&gt;
* Messung Wechselspannung/-Strom, Berechnung Wirkungsgrad, cosinus phi&lt;br /&gt;
&lt;br /&gt;
=Links und Downloads=&lt;br /&gt;
&lt;br /&gt;
[http://www.roboternetz.de/community/threads/30495-Projekt-Sinuswechselrichter-12V-230V roboternetz.de Sinuswechselrichter-12V-230V]&lt;br /&gt;
&lt;br /&gt;
[http://www.avr-asm-download.de/praesentation/Teil_8_Beispiel_11.pdf Ein Sinusgenerator mit AVR-Timer]&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
[[Datei:Source_Sinuswandler.zip]]&lt;br /&gt;
&lt;br /&gt;
Schaltplan:&lt;br /&gt;
[[Datei:Eagle_Sinuswandler.zip]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sinuswechselrichter1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sinuswechselrichter2.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Link für Nachricht an den Autor: [http://www.mikrocontroller.net/user/show/AndreasR Andreas Richter]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=90053</id>
		<title>LPC1114 Breakout Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=90053"/>
		<updated>2015-10-17T08:54:44Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: /* Schaltplan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Nachdem der AVR jahrelang seine Dienste verrichtet hat, kommt man heute eigentlich nicht darum herum, auch mal über den (8-Bit) - Tellerrand zu schauen. Die ARM-CPU’s drängen sich geradezu auf und werden auch für den Bastler immer interessanter. Mittlerweile ist ein LPC1114 billiger als ein ATmega32. Und das bei einer höheren Performance und mehr verfügbarem RAM. Was mich bisher vom Einsatz abgehalten hat ist die Tatsache dass die meisten ARM Controller nur als SMD- Package (LQFP) erhältlich sind und das fehlende EEProm zum Ablegen von Konfigurationsparametern. Um diese beiden Nachteile zu eliminieren und insgesamt die Einstiegshürde für den Einsatz eines Cortex-M0 zu senken, habe ich das hier beschriebene Breakout-Board entworfen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LPC1114-Breakout.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==Features==&lt;br /&gt;
* Steckbrett-kompatibel&lt;br /&gt;
* Konfigurations-EEProm optional bestückbar (I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C)&lt;br /&gt;
* Quarz optional bestückbar&lt;br /&gt;
* Cortex 10-pin 0.05&amp;quot; JTAG/SWD Debug-Schnittstelle&lt;br /&gt;
&lt;br /&gt;
==Schaltplan==&lt;br /&gt;
[[Bild:LPC1114-Schaltplan.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Es werden im Wesentlichen alle IO-Pins des LPC auf Stiftleisten geführt. Ein Quarz und ein I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEProm sind optional bestückbar. Die Debug-Schnittstelle ist direkt mit den SWD-Pins des Prozessors verbunden.&lt;br /&gt;
{{Warnung|Der LPC1114 darf maximal mit einer Versorgungsspannung von 3,6V betrieben werden! &amp;lt;br/&amp;gt;Eine Versorgungsspannung von 5V tötet ihn!}}&lt;br /&gt;
Die Eingänge sind aber 5V-tolerant.&lt;br /&gt;
Im Anhang befinden sich die Eagle-Files. &amp;lt;br/&amp;gt;Die Fertigung der Platinen bei einem chinesischen Hersteller hat mich 16USD / 5 Platinen incl. Versand gekostet.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Im unten verlinkten Sourcecode-Paket befindet sich ein HelloLpc1114 Projekt für die LPCXpresso-IDE. Enthalten ist auch ein Treiber für das I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEprom.  Die Software ist für den Betrieb mit einem 12 MHz-Quarz konfiguriert. Die interne PLL erhöht den Takt auf 48 MHZ. Falls das Board mit dem internen RC-Oszillator oder mit einer anderen Frequenz betrieben werden soll, muss die Takt-Konfiguration angepasst werden. Dazu muss die Datei system_LPC11xx.c editiert werden. Damit man sich nicht durch die einzelnen Bit-Definitionen hangeln muss gibt es das Java-Tool [http://sourceforge.net/projects/cmsisconfig CMSIS Configurator].&lt;br /&gt;
&lt;br /&gt;
[[Bild:CMSIS-Config.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Das Projekt referenziert die CMSIS-Library CMSIS_CORE_LPC11xx. Sie ist Bestandteil des NXP LPCXpresso Installationspaketes.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Link für Nachricht an den Autor: [http://www.mikrocontroller.net/user/show/AndreasR Andreas Richter]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
[[Datei:LPC1114_Example.zip]]&lt;br /&gt;
&lt;br /&gt;
Eagle-Files:&lt;br /&gt;
[[Datei:LPC1114_Breakout_Eagle.zip]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Category:ARM]]&lt;br /&gt;
[[Category:LPC1x]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=90052</id>
		<title>LPC1114 Breakout Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=90052"/>
		<updated>2015-10-17T08:53:49Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Nachdem der AVR jahrelang seine Dienste verrichtet hat, kommt man heute eigentlich nicht darum herum, auch mal über den (8-Bit) - Tellerrand zu schauen. Die ARM-CPU’s drängen sich geradezu auf und werden auch für den Bastler immer interessanter. Mittlerweile ist ein LPC1114 billiger als ein ATmega32. Und das bei einer höheren Performance und mehr verfügbarem RAM. Was mich bisher vom Einsatz abgehalten hat ist die Tatsache dass die meisten ARM Controller nur als SMD- Package (LQFP) erhältlich sind und das fehlende EEProm zum Ablegen von Konfigurationsparametern. Um diese beiden Nachteile zu eliminieren und insgesamt die Einstiegshürde für den Einsatz eines Cortex-M0 zu senken, habe ich das hier beschriebene Breakout-Board entworfen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LPC1114-Breakout.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==Features==&lt;br /&gt;
* Steckbrett-kompatibel&lt;br /&gt;
* Konfigurations-EEProm optional bestückbar (I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C)&lt;br /&gt;
* Quarz optional bestückbar&lt;br /&gt;
* Cortex 10-pin 0.05&amp;quot; JTAG/SWD Debug-Schnittstelle&lt;br /&gt;
&lt;br /&gt;
==Schaltplan==&lt;br /&gt;
[[Bild:LPC1114-Schaltplan.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Es werden im Wesentlichen alle Pins des LPC auf Stiftleisten geführt. Ein Quarz und ein I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEProm sind optional bestückbar. Die Debug-Schnittstelle ist direkt mit den SWD-Pins des Prozessors verbunden.&lt;br /&gt;
{{Warnung|Der LPC1114 darf maximal mit einer Versorgungsspannung von 3,6V betrieben werden! &amp;lt;br/&amp;gt;Eine Versorgungsspannung von 5V tötet ihn!}}&lt;br /&gt;
Die Eingänge sind aber 5V-tolerant.&lt;br /&gt;
Im Anhang befinden sich die Eagle-Files. &amp;lt;br/&amp;gt;Die Fertigung der Platinen bei einem chinesischen Hersteller hat mich 16USD / 5 Platinen incl. Versand gekostet.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Im unten verlinkten Sourcecode-Paket befindet sich ein HelloLpc1114 Projekt für die LPCXpresso-IDE. Enthalten ist auch ein Treiber für das I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEprom.  Die Software ist für den Betrieb mit einem 12 MHz-Quarz konfiguriert. Die interne PLL erhöht den Takt auf 48 MHZ. Falls das Board mit dem internen RC-Oszillator oder mit einer anderen Frequenz betrieben werden soll, muss die Takt-Konfiguration angepasst werden. Dazu muss die Datei system_LPC11xx.c editiert werden. Damit man sich nicht durch die einzelnen Bit-Definitionen hangeln muss gibt es das Java-Tool [http://sourceforge.net/projects/cmsisconfig CMSIS Configurator].&lt;br /&gt;
&lt;br /&gt;
[[Bild:CMSIS-Config.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Das Projekt referenziert die CMSIS-Library CMSIS_CORE_LPC11xx. Sie ist Bestandteil des NXP LPCXpresso Installationspaketes.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Link für Nachricht an den Autor: [http://www.mikrocontroller.net/user/show/AndreasR Andreas Richter]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
[[Datei:LPC1114_Example.zip]]&lt;br /&gt;
&lt;br /&gt;
Eagle-Files:&lt;br /&gt;
[[Datei:LPC1114_Breakout_Eagle.zip]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Category:ARM]]&lt;br /&gt;
[[Category:LPC1x]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=90051</id>
		<title>LPC1114 Breakout Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=LPC1114_Breakout_Board&amp;diff=90051"/>
		<updated>2015-10-17T08:52:20Z</updated>

		<summary type="html">&lt;p&gt;Andreasr: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Nachdem der AVR jahrelang seine Dienste verrichtet hat, kommt man heute eigentlich nicht darum herum, auch mal über den (8-Bit) - Tellerrand zu schauen. Die ARM-CPU’s drängen sich geradezu auf und werden auch für den Bastler immer interessanter. Mittlerweile ist ein LPC1114 billiger als ein ATmega32. Und das bei mehr RAM und einer höheren Performance. Was mich bisher vom Einsatz abgehalten hat ist die Tatsache dass die meisten ARM Controller nur als SMD- Package (LQFP) erhältlich sind und das fehlende EEProm zum Ablegen von Konfigurationsparametern. Um diese beiden Nachteile zu eliminieren und insgesamt die Einstiegshürde für den Einsatz eines Cortex-M0 zu senken, habe ich das hier beschriebene Breakout-Board entworfen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LPC1114-Breakout.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==Features==&lt;br /&gt;
* Steckbrett-kompatibel&lt;br /&gt;
* Konfigurations-EEProm optional bestückbar (I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C)&lt;br /&gt;
* Quarz optional bestückbar&lt;br /&gt;
* Cortex 10-pin 0.05&amp;quot; JTAG/SWD Debug-Schnittstelle&lt;br /&gt;
&lt;br /&gt;
==Schaltplan==&lt;br /&gt;
[[Bild:LPC1114-Schaltplan.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Es werden im Wesentlichen alle Pins des LPC auf Stiftleisten geführt. Ein Quarz und ein I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEProm sind optional bestückbar. Die Debug-Schnittstelle ist direkt mit den SWD-Pins des Prozessors verbunden.&lt;br /&gt;
{{Warnung|Der LPC1114 darf maximal mit einer Versorgungsspannung von 3,6V betrieben werden! &amp;lt;br/&amp;gt;Eine Versorgungsspannung von 5V tötet ihn!}}&lt;br /&gt;
Die Eingänge sind aber 5V-tolerant.&lt;br /&gt;
Im Anhang befinden sich die Eagle-Files. &amp;lt;br/&amp;gt;Die Fertigung der Platinen bei einem chinesischen Hersteller hat mich 16USD / 5 Platinen incl. Versand gekostet.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Im unten verlinkten Sourcecode-Paket befindet sich ein HelloLpc1114 Projekt für die LPCXpresso-IDE. Enthalten ist auch ein Treiber für das I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-EEprom.  Die Software ist für den Betrieb mit einem 12 MHz-Quarz konfiguriert. Die interne PLL erhöht den Takt auf 48 MHZ. Falls das Board mit dem internen RC-Oszillator oder mit einer anderen Frequenz betrieben werden soll, muss die Takt-Konfiguration angepasst werden. Dazu muss die Datei system_LPC11xx.c editiert werden. Damit man sich nicht durch die einzelnen Bit-Definitionen hangeln muss gibt es das Java-Tool [http://sourceforge.net/projects/cmsisconfig CMSIS Configurator].&lt;br /&gt;
&lt;br /&gt;
[[Bild:CMSIS-Config.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Das Projekt referenziert die CMSIS-Library CMSIS_CORE_LPC11xx. Sie ist Bestandteil des NXP LPCXpresso Installationspaketes.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Link für Nachricht an den Autor: [http://www.mikrocontroller.net/user/show/AndreasR Andreas Richter]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sourcecode:&lt;br /&gt;
[[Datei:LPC1114_Example.zip]]&lt;br /&gt;
&lt;br /&gt;
Eagle-Files:&lt;br /&gt;
[[Datei:LPC1114_Breakout_Eagle.zip]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;br /&gt;
[[Category:ARM]]&lt;br /&gt;
[[Category:LPC1x]]&lt;/div&gt;</summary>
		<author><name>Andreasr</name></author>
	</entry>
</feed>