SPS mit ATmega: Unterschied zwischen den Versionen

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche
KKeine Bearbeitungszusammenfassung
KKeine Bearbeitungszusammenfassung
Zeile 132: Zeile 132:


==Uhr==
==Uhr==
(#ifdef WITH_CLOCK)
<syntaxhighlight lang="c">(#ifdef WITH_CLOCK)</syntaxhighlight>
Freilaufende Uhr mit DCF77-Synchronisierung.
Freilaufende Uhr mit DCF77-Synchronisierung.



Version vom 28. Februar 2016, 10:58 Uhr

von andreasr

Viele Steuerungsaufgaben in der Hausautomation können mit einfachen SPS-Funktionen gelöst werden (Treppenhaus-Automat, Tast-Funktion, Und-/Oder-/Xor-/Not-Funktionen, Flankenerkennung, Selbsthaltung, Reaktion auf Zählerstände, …). Der Nachteil einer käuflichen SPS ist der hohe Preis. Auf der anderen Seite kann ein aktueller Mikrocontroller die SPS-Funktionen spielend leicht abbilden. Nachteil ist hier aber die komplizierte Programmierung bzw. die Pflege des Programms. C und C++ sind nicht unbedingt die erste Wahl für die Programmierung logischer Ablaufsequenzen. Was liegt näher als mit einen Mikrocontroller eine SPS zu implementieren, die sich in einer AWL-ähnlichen Sprache programmieren lässt?

Features

  • 12 oder 24V Betriebsspannung
  • Leiterplattengröße halbes Euro-Format
  • 8 Eingänge
  • 8 Ausgänge, 500mA, direktes Schalten induktiver Lasten
  • möglichst preiswerte und einfach zu beschaffende Komponenten
  • optinale Zusatzmodule anschließbar, z.B. LCD, Taster, RFM12, DCF77-Empfänger
  • optionale Softwaremudule realiserbar, z.B. Zeitschaltuhr, smarthomatic Power Switch Implementation

Theory of Operation

Die Abarbeitung eines SPS-Programmes erfolgt innerhalb von sogenannten Zyklen. Das sind feste Zeitabschnitte, in denen das gesamte Programm durchlaufen wird und aus Eingangssignalen Ausgangssignale gebildet (berechnet) werden. Diese Zeitabschnitte sollten möglichst kurz sein, da sie die minimale Reaktionszeit bestimmen. Da mit einer SPS üblicherweise kontaktbehaftete Steuerungen nachgebildet werden ist eine Zykluszeit von 10-100 ms meistens ausreichend. 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. Um die Komplexität gering zu halten, besteht jeder Programm-Befehl aus 2 Bytes; einem Opcode und einer Adresse. Als Ergebnis-Zwischenspeicher wird ein Akkumulator-Register benutzt. Operationen, die 2 Operanden verarbeiten benutzen als zweiten Operanden ebenfalls den Akkumulator.

Hardware

Als Mikrocontroller wird ein ATmega328 verwendet. Um genügend Eingänge und Ausgänge zur Verfügung zu haben wird eine Porterweiterung verwendet. Die Ansteuerung der Schieberegister erfolgt per Software-SPI. Das SPS-Programm wird im EEProm des Mikrocontrollers abgelegt und zur Laufzeit in das RAM geladen. Um Zusatzfunktionalitäten zu realisieren, werden einige Port-Pins des Mikrocontrollers auf einer Stiftleiste herausgeführt. 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. 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. Dem ATmega selbst hat einen Spannungsbereich von ca. 3V – 5V falls man mit der Taktfrequenz nicht über 8 MHz geht. Die Versorgungsspannung kann sich in einem weiten Bereich bewegen und wird im Wesentlichen durch den LM2574 begrenzt. Der LM2574 hat eine max. Eingangsspannung von 45 V. Es müssen nur die Vorwiderstände für die Optokoppler angepasst werden, dass der Strom durch die LED's ungefähr 10 mA beträgt; also etwa 1,2k Ohm für 12V und 2,2kOhm für 24V. Die Eingangsbeschaltung für einen einzelnen Eingang sieht so aus:

TODO: Eagle

Optional können 2 Eingänge über Optokoppler isoliert mit Netzspannung angesteuert werden. Es wird ein kapazitiver Spannungsteiler verwendet. Die Entprellung muss mit einer entsprechenden Zeitkonstante ausgeführt werden, um die 100Hz-Frequenz zu eliminieren.

TODO: Eagle

Sicherheitshinweis

Das Arbeiten mit Netzspannung sind die einschlägigen Sicherheitsvorschriften ezüglich Berührungsschutz, Isolationsabstand, Kriechstrecken etc. einzuhalten.

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. Freilaufddioden für induktive Lasten sind integriert. Die Ausgangsstufe sieht wie folgt aus:

Software

Die eigentliche Befehlsausführung ist in der Funktion

void SPSExec(const uint8_t* prog)

implementiert.

Es werden immer 2 Bytes gelesen: Opcode und Adresse. Zunächst wird der Opcode aufgespalten in die Operand und in Attribute.


TODO: Grafik

Die Operanden opLoad, opAND, opOR, opXOR können mit dem Attribute attrSubBlock kombiniert werden. Das führt dazu, dass die folgenden Berechnungen bis zum Operanden opEnd als Teilausdruck aufgefasst werden, der anschließend mit dem aktuellen Ergebnis kombiniert wird (Klammerausdruck). Zur Berechnung von Teilausdrücken wird ein Stack benutzt.

Danach wird das Adress-Byte ausgewertet. Das Adress-Byte kodiert das Device, einen Byte-Index und die Bit-Nummer:

TODO: Grafik

Schreiben des SPS-Programmes

Die Programmierung soll möglichst einfach sein aber auch intuitiv. Das wird erreicht durch eine Kombination von bestimmten Operanden- und Adress-Makros. In Wirklichkeit ist das Programm eine Deklaration eines Byte-Arrays was im EEProm abgelegt wird. Zum Einspielen eines neuen SPS-Programmes reicht es also, das EEProm des ATmega neu zu beschreiben (= Speicherprogrammierbare Steuerung)

Beispiele

Q1 = I1 AND (I2 OR NOT I3)

#define I1		IN(0)
#define I2		IN(1)
#define I3		IN(2)
#define Q1		OUT(0)

uint8_t EEDataSPSCode[] EEMEM= {
	LD, 	I1,
	AND+KLAUF, 0,	// (
		LD, I2,
		OR+NOT, I3,
	KLZU, 0, 	// )
	ST,	Q1,
	EXIT,
};

Selbsthaltung, I1 = Q1 Ein, !I2 = Q1 Aus

#define I1		IN(0)
#define I2		IN(1)
#define Q1		OUT(0)

uint8_t EEDataSPSCode[] EEMEM= {
	LD, 	I1,
	S,	Q1,	
	LD,	NOT+I2
	R,	Q1,		// dominierend Aus
	EXIT,
};

Flankenerkennung steigende Flanke an I1 setzt Q1

#define I1		IN(0)
#define Q1		OUT(0)
#define Merk1		M(1)

uint8_t EEDataSPSCode[] EEMEM= {
	LD,			I1,
	FP,			Merk1,		// Flanke Positiv; braucht Hilfs-Merker
	S,			Q1,
	EXIT,
};

Der Compiler legt das Array EEDataSPSCode als EEProm-File ab.

Timer

Counter

Zusatzfunktionen

Um die Flexibilität zu erhöhen, können Zusatzmodule in der Software aktiviert werden. Aktuell gibt es folgende Module:

Uhr

(#ifdef WITH_CLOCK)

Freilaufende Uhr mit DCF77-Synchronisierung.

Zeitschaltuhr

(#ifdef WITH_CLOCK_SWITCH)

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) Die Zeitschaltuhr bezieht die Zeitinformation aus dem Modul Uhr (#ifdef WITH_CLOCK) Es können absulute Zeiten sowie Zeiten relativ zum Sonnen- Auf-/Untergang ausgewählt werden.

smarthomatic - Potokoll

(#ifdef WITH_SHC)

Es wird ein 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. 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.