Home

News

Schnelleinstieg

Hintergrund

Doku

Bilder

Download

Forum

Kontakt

4.2 Beschreibung Knotensoftware („C“-Implementation)

Die Knotensoftware wurde von dem Grundgerüst/Rahmenprogramm abgeleitet. Daraus resultiert dann eine Form der Projektsoftware. Die Projektsoftware ist das Hauptprogramm zu einem Projekt bzw. alle Dateien/Module die zum Projekt gehören, nicht aber die Include-Files aus dem "\inc"-Verzeichnis. So ist RelS (RelaisApplikation) zum Beispiel eine Projektsoftware, "relais.c" zählt dagegen zu den Include-Files. In den Include-Files sind die grundlegenden Funktionen zur Steuerung der Hardware abgelegt. Diese können dann von mehreren Projekten eingebunden werden.

 

4.2.1 Projektsoftware

Die bereits entstandene Projektsoftware ist hier aufgeführt und soll als Beispiel/Vorlage für Erweiterungen dienen.

4.2.1.1 Grundgerüst/Rahmensoftware

Die aktuelle Rahmensoftware (Rahm1.10) benötigt ohne Erweiterungen 1660 Bytes Programmspeicher. Hiermit ist eine grundlegende Buskommunikation und das Signalisieren eintreffender Telegramme abgedeckt. Das eigentliche Hauptprogramm/Hauptaufgabe der Software muß noch, genau wie die Routinen zur Abarbeitung von eintreffenden Telegrammen, ausformuliert/erstellt werden.

Die Datei DefProjekt.h ist für Definitionen (Konstanten, Prototypen, Variablen) gedacht, die genau zu diesem speziellen Projekt gehören. Sie übernimmt also die Aufgabe, die eigentlich Rahm1.10.h abdecken müßte. Einige der Include-Files brauchen Definitionen aus dieser Datei, deswegen wurde der Dateiname "DefProjekt.h" für jedes einzelne Projekt festgelegt.

Eingebundene Includefiles müssen dem makefile bekannt gemacht werden.

Die Funktionen von Knotenbefehl werden im Abschnitt Includefiles can.c beschrieben.

Hier folgt eine kurze Auflistung der Rahmensoftware, dieser Teil kann bei der Vorstellung der übrigen Projektsoftware somit entfallen:

/******************************************************************************
*
* Dateiname: Rahmensoftware.c
* Version: v1.10 / 1660Bytes
* Funktion: Softwaregrundgerüst als Grundlage zur Erweiterung
* Datum: 1.2.2002
*
******************************************************************************/

Hier folgen die Include-Anweisungen:
#include <io.h>
#include
<sig-avr.h>
#include <interrupt.h>

#include
"Rahmensoftware.h"
#include
"inc\globals.h" // Globale Variablendefinitionen (für alle Projekte gueltig)
// hier folgen dann die projektspezifischen Includes, nicht vergessen diese Includes dann auch im Makefile anzugeben!!!
// z.B. #include "inc\relais.h" // Taster- und Relaisroutinen
// ---------------------------------------------------------------------------


Initialisierung des Atmelcontrollers inkl. Einstellung der MCUCR und GIMSK Register...
void AtmelInit(void)
{

// ungebrauchte Pins auf hochohmige Eingänge stellen
outp(0x00,DDRA); // PortA initialisieren
outp(0x00,PORTA);
outp(0x00,DDRB); // PortB initialisieren
outp(0x00,PORTB);
outp(0x00,DDRC); // PortC initialisieren
outp(0x00,PORTC);
outp(0xF0,DDRD); // PortD initialisieren
outp(0xE0,PORTD);
outp(0x80,GIMSK); // Externe Interruptanforderung 1 aktivieren
outp(0x00,MCUCR); // Interrupt bei LowLevel aktivieren

}
// ---------------------------------------------------------------------------

Hauptprogramm:
int main(void)
{

AtmelInit();
CANInit(); // (-> can.c)
sei(); // Atmelinterrupts freigeben
while (1) // Hauptprogrammschleife
{

cli(); // Interruptsperre
// TasterAbfragen(); // Tasterzustaende abfragen und darauf reagieren (->relais.c)
sei(); // Interruptsperre wieder aufheben

}

}
// ---------------------------------------------------------------------------

Interruptroutine zur Abarbeitung der anstehenden CANBus-Telegramme:
SIGNAL(SIG_INTERRUPT1) /* signal handler for external interrupt int1 */
{

if ((CANLesen(INTR) & 0x01) == 1) // Interruptregister (CAN-Controller) einlesen und auf ReceiveInterrupt reagieren

EMPFANG(); // (->can.c)

}
// ---------------------------------------------------------------------------

Routinen zur Bearbeitung eingehender CAN-Telegramme:

/*********************************************************************
** Folgende Unterprogramme werden noch im Interrupt1 ausgefuehrt **
** Sie werden aufgerufen, wenn ein Telegramm fuer das entsprechende**
** MO eingetroffen ist **
*********************************************************************/

// Routinen eintragen, die aufgerufen werden sollen, wenn ein Telegramm auf einem MO eingetroffen ist
void MO0soft(void) //** Dieses MO ist zum Senden reserviert und darf daher nicht zum Empfang benutzt werden
{ }
void MO1soft(void)
{
// z.B.
// TelegrammRelais1(); // (->relais.c)

}
void MO2soft(void)
{ }
void MO3soft(void)
{ }
void MO4soft(void)
{ }
void MO5soft(void)
{ }
void MO6soft(void)
{ }
void MO7soft(void)
{ }
void MO8soft(void)
{ }
void MO9soft(void)
{ }
void MO10soft(void)
{ }
void MO11soft(void)
{ }
void MO12soft(void)
{ }
void MO13soft(void)
{ }
void MO14soft(void)
// ** Broadcast MO, hier treffen Nachrichten ein, die fuer alle Knoten
// ** relevant sind, ID=1 (darf nicht veraendert werden)

{ }
void MO15soft(void) // ** Telegramm fr Knotenadresse eingetroffen
{

KnotenBefehl(); // (->can.c)

}
// ---------------------------------------------------------------------------

 

 

4.2.1.2 RelS (RelaisSoftware)

RelS steuert die IO-Applikation (Relaiskarte) mit bis zu 4 Relais/ 4 Tastern. In der Hauptprogrammschleife werden die an die CAN-Controller Porterweiterung angeschlossenen Taster zyklisch abgefragt. Bei Änderungen werden die vordefinierten Telegramme verschickt, und die lokal auszuführenden Schaltvorgänge erledigt. Detailierte Beschreibung siehe Kapitel 3.2.

Verwendete Includefiles: can.h sendtele.h relais.h

 

4.2.1.3 232S (RS232Software)

Die 232Software ist momentan noch nicht nach C portiert, daher hier der Verweis auf die Assembler-Version in Kapitel 4.1.2.2.

 

4.2.1.4 RolR (RolladenRelais)

Diese Software beruht auf der Hardware der IO-Applikation. Es werden, je nach Einstellung beim Compilieren (in DefProjekt.h), etweder 2 Rolläden (MO1 und MO2) unterstützt, oder ein Rolladen (MO1) und 2 frei verwendbare Relais (MO3 und MO4).
Per CAN-Telegramm wird die gewünschte Rolladenstellung an den Rolladen übermittelt. Hierbei entspricht der Wert 0 der oberen Rolladenstellung (offen), der Wert 100 entspricht dem geschlossenen Rolladen. Alle Werte dazwischen fahren den Rolladen in eine zugehörige Zwischenstellung. Da die Rolladenmotoren zwar eine Endabschaltung haben, aber die genaue Position dazwischen nicht bestimmbar ist, muß der Rolladen über eine "Fahr"zeitsteuerung bedient werden. Dazu wird die Fahrzeit für eine Fahrt (offen -> geschlossen, oder geschlossen -> offen) gemessen durch 100 geteilt und als Wert in Millisekunden im EEProm des uC bei Adresse 0xF8 (Rolladen1), bzw 0xF9 (Rolladen2) abgelegt (Variable: Roll1Timer, Roll2Timer). Bei Programmstart wird der Zeitwert eingelesen und erwartet, daß der Rolladen offen steht. Timer0 wird als Millisekundentimer initialisiert und ruft alle <Roll1Timer> bzw. <Roll2Timer> Millisekunden die Abarbeitungsroutine auf. Hier wird verglichen, ob der Rolladen bewegt werden muß und in welche Richtung dies geschehen soll (Roll1Pos und Roll1ZielPos wird verglichen und das entsprechende Relais geschaltet). Ein vorzeitiger Stopp des Rolladens kann durch ein spezielles Telegramm erreicht werden. Sinnvoll kann dies z.B. in der interaktiven Rolladensteuerung sein (Taster für Auf/Ab). Hier kann von der steuernden Applikation z.B. bei Druck auf die Taste hoch, der Wert 0 an den Rolladen gesendet werden. Der Rolladen hebt sich. Wird der Taster dann losgelassen, so sendet die steuernde Applikation ein Stopp-Telegramm an den Rolladen.

Leider ist die Wiederholpositioniergenauigkeit bei vielen kleinen Bewegungen nur sehr gering, d.h. zehnmal 2% senken ist nicht identisch mit einmal 20% senken. Damit sich im Laufe der Zeit keine größeren Differenzen zwischen gewünschter Rolladenposition und tatsächlicher Position ergeben, wird die programminterne Positionsvariable bei jeder Fahrt an den Anschlag (oben oder unten) neu kalibriert. Dazu wird der Rolladen 10% weiter gefahren als nötig, so ist sichergestellt, daß er wirklich an den Anschlag gefahren ist. Für die Positionsvaribale bedeutet dies, daß sie den Wert 1 einnimmt für Rolladen ganz offen, und den Wert 99 für ganz geschlossen (bei 0 bzw. 100 würde eine ständige Rekalibrierung durchgeführt und das Relais würde nie abgeschaltet). Durch die Endabschalter in den Rohrmotoren besteht keine Gefahr für den Motor/Rolladen bei der Kalibrierung.

Die aktuelle Position und die anzufahrende Position lassen sich per Statusabfrage-Kommando an den Rolladen auslesen. Der "Rolladen" sendet dazu ein Telegramm an eine anzugebende Adresse.

Das Telegrammformat zur Steuerung der Relais/Rolladen wird im Kapitel 4.2.2.5 rolladen.h ausführlich beschrieben

Verwendete Includefiles: can.h sendtele.h timer.h relais.h rolladen.h funktionen.h

 

4.2.1.5 Dimm (Dimmersoftware)

Steuert bis zu 16 Sensordimmer (SLB0587) + 4 Relais

Verwendete Includefiles: can.h sendtele.h timer.h relais.h

 

4.2.1.6 MenS (MenüSystemSoftware)

Die Menüsoftware ist eine Dialogsoftware für den Benutzer. Über den angeschlossenen Cursortasterblock und ein LCD Display kann er durch die Untermenüs navigieren. Die Navigation wird mit einer Statemaschine gelöst. Jeder Tastendruck läßt die Statemaschine in einen anderen Zustand springen, dabei wird auch die Displayausgabe aktualisiert.

 

Verwendete Includefiles: can.h sendtele.h timer.h funktionen.h canports.h lcd.h uart.h

 

4.2.1.7 DMen (DimmerMenüsoftware)

Die DimmerMenüsoftware basiert auf der Menüsoftware und deren Hardware. Sie wurde ergänzt durch eine Tastenmatrix, die sparsamer mit der Anzahl der verwendeten Portpins umgeht. Die "Dimmerdirekttasten" senden beim Niederdrücken einen Dimm-Befehl an die Dimmerknoten, beim Loslassen wird ein Dimm-Stop-Befehl verschickt. Zusätzlich können noch Wandtaster angeschlossen werden, die die herkömmlichen Lichtschalter ersetzen. Zum Einsatz (unter der Tasterplatine angeordnet) kam hier die Nachfolgeversion des ursprünglichen Buskopplers (Foto: Buskoppler(kleiner)).

Verwendete Includefiles: can.h sendtele.h timer.h funktionen.h canports.h lcd.h

 

4.2.1.8 Ther (Thermometersoftware)

 

Verwendete Includefiles: can.h sendtele.h timer.h funktionen.h lcd.h ds1820.h

 

4.2.1.9 ZSUr (ZeitSchaltUhR)

Die Hardware der Zeitschaltuhr besteht, neben dem obligatorischen Buskoppler, aus einem oder mehreren I2C-EEProms (24C64, 64kBit) und optional aus einem LCD-Display (2x16), das die aktuelle Zeit ausgibt. Die externen EEProms werden über den I2C-Bus angesprochen. Die Firmware ist so ausgelegt, daß mehrere 24C64-Speicherbausteine angeschlossen werden können, dadurch wird das Speichervermögen des Zeitschaltknotens erhöht. In der Standardbestückung mit 8kByte besteht so ausreichend Platz für 512 Schaltzeitpunkte und Telegramme.

Die Schaltzeitpunkte können folgendermaßen aussehen:

  • einmalige Telegramme (z.B. am 10.4.2002 um 21:00Uhr Lampen einschalten)
    (EinmalTelegramme), Speicher für max. 96 Telegramme/Zeitschaltpunkte reserviert (ohne Speichererweiterung)
  • täglich wiederkehrende Telegramme (z.B. täglich um 21:00Uhr Rolläden schließen)
    (täglicheTelegramme), Speicher für max. 224 Telegramme/Zeitschaltpunkte
  • wöchentlich wiederkehrende Telegramme (z.B. jeden Samstag Heizkoerperventile öffnen/schließen, damit diese sich nicht festsetzen... usw.)
    (wöchentlicheTelegramme), Speicher für max. 176 Telegramme/Zeitschaltpunkte
  • relativ zur aktuellen Uhrzeit gewählte Zeitschaltpunkte (z.B. Timerschaltung, Licht in 30min ausschalten)
    (kurzTelegramme), Speicher für max. 16 Telegramme/Zeitschaltpunkte

Die Hardware der Zeitschaltuhr besitzt selbst keinerlei Bedienknöpfe, die Telegramme müssen per PC in den Knoten übertragen werden. Ausnahme hiervon: Die kurzTelegramme sind dafür gedacht, daß andere Knoten (z.B. IO-Applikation, Taster) solche kurzTelegramme verschicken. Diese dürfen dann, wegen der Beschränkung der CAN-Nutzdatenlänge von 8 Bytes, nur 4 Datenbytes umfassen (->kurzTelegramm).

Die interne Uhr des Zeitschaltknotens wird durch ZeitTelegramme (CAN-ID 50) entweder vom PC oder vom DCF77-Knoten abgeglichen/gestellt.


Firmwarebeschreibung:

Zuänachst werden die nächsten zu versendenden Telegramme aus den einzelnen Bereichen gelesen und die entsprechenden Variablen vorbesetzt. Dabei werden Telegramme, die zu einem vergangenen Zeitpunkt verschickt werden sollten, ignoriert. (wichtig, wenn Knoten z.B. zurückgesetzt wird und wieder anfahren soll).

Die Hauptprogrammschleife ruft nacheinander die Routinen zur Abarbeitung der einzelnen Zeitschaltarten (einmal, täglich, wöchentlich und kurz) auf. Jeder 256. Durchgang (etwa alle 13s) wird die Displayausgabe (hh:mm) aktualisiert. Es kann also vorkommen, daß die angezeigte Zeit für kurze Zeit nicht der aktuellen Zeit entspricht.

Die Schaltarten "einmal", "täglich" und "wöchentlich" sind sich in ihrem Ablauf sehr ähnlich. Zunächst wird geprüft, ob die Zeit des nächsten zu versendenden Telegramms erreicht ist. Ist dies der Fall, so wird das Telegramm verschickt und das nächste aus dem Speicher geladen und die Variablen (die das nächste Telegramm und den Zeitpunkt repräsentieren) wieder neu besetzt. Dies ist möglich, da die PC-Software sicherstellt, daß die Telegramme in chronologischer Reihenfolge in den Speicher geschrieben werden. Deshalb mußte auch eine Trennung zwischen wöchentlicher und täglicher Telegramme stattfinden, da nur so eine eindeutige chronologische Reihenfolge eingehalten werden kann.

Trifft ein kurzTelegramm ein, so wird der Schaltzeitpunkt aus der aktuellen Uhrzeit und der relativen Zeitangabe (in Sekunden) aus dem Telegramm berechnet. Dies ist bei einem Zielzeitpunkt am nächsten Tag relativ codeintensiv. Die errechneten und übergebenen Werte werden in externenEEProm an einer freien Stelle abgelegt. Da die Telegramme nicht in der Reihenfolge eintreffen, in der sie auch ausgeführt werden sollen (z.B. 30minuten-Timer vor 10minuten-Timer) müssen alle möglichen Schaltzeitpunkte und Telegramme in jeder Sekunde ausgelesen werden und ihr Schaltzeitpunkt mit der momentan aktuellen Zeit verglichen werden. Das Vorhalten aller Telegramme im Speicher kommt aus Platzgründen nicht in Frage. Da das Auslesen aus dem externen EEProm einige Zeit in Anspruch nimmt, wurde die maximale Anzahl der KurzzeitTimer auf 16 begrenzt. Theoretisch könnten bis zu ca. 40 Telegramme pro Sekunde aus dem Speicher ausgelesen werden. Es muß aber neben dem Auslesen auch noch die normale Buskommunikation (Knotenbefehle, extEEPromLesen...) abgewickelt werden.

Für das Beschreiben des externen EEProms sind folgende Befehle notwendig:

  • extEEPromSchreiben: Nimmt EEProm-Adresse und den Inhalt von 4 Datenbytes entgegen und trägt diesen im externen EEProm ein. Antwortpaket der Zeitschaltuhr enthält u.a. die Fehlernummer bzw. eine Bestätigung, daß alles fehlerfrei verlief. (Kommandotelegramm muß in MO12 eintreffen)
  • extEEPromLesen: Liest übergebene EEProm-Adresse aus und schickt deren Inhalt an die Absendeadresse. (MO11)
  • extEEPromLoeschen: Löscht sämtliche angeschlossene extEEProm-Speicherbausteine. (MO10)

Um den Protokolloverhead klein zu halten (die CAN-Telegramme beinhalten ja bekanntlich nur 8 Nutzbytes) wird für jeden Befehl eine eigene CAN-ID reserviert.

Der Knoten muß nach dem Programmieren durch ein spezielles Telegramm zurückgesetzt werden (Uhrzeit bleibt erhalten).
Per Definition dürfen die Bereiche für täglicheTelegramme und für wöchentlicheTelegramme nicht nur mit einem Telegramm befüllt sein, sonst wird dieses Telegramm zur geforderten Uhrzeit mehrfach verschickt. (Eine Abfrage, ob Telegramm schon verschickt wurde, wurde aus Speicherplatzgründen nicht implementiert). Das Einhalten dieser Bedingung muß die PC-Programmier/Konfigurationssoftware sicherstellen.

Im Anhang (Kap 6.11) werden die Telegrammformate und die Speicherorganisation tabellarisch aufgeführt:

Verwendete Includefiles: can.h sendtele.h timer.h funktionen.h lcd.h i2c.h 24C64.h zeit.h

 

4.2.1.10 MeIR (MenüsystemIR)

Das MenüsystemIR bietet die Möglichkeit per IR-Fernbedienung bestimmte Telegramme zu versenden, um damit beispielsweise Lampen, Rolläden, Steckdosen usw. zu steuern. Die Hardware besteht, neben einem Buskoppler, lediglich aus einem IR-Empfänger (z.B. TSOP1736), dessen Ausgang an PD2/Int0 angeschlossen ist. Die Dekodierung der eintreffenden IR-Signale wird von den Routinen im Modul ir.c übernommen. Als Fernbedienung kann jede RC5 kompatible Fernbedienung herhalten. Für meine Zwecke setze ich eine alte Hauppauge Fernbedienung ein (Bild mit Tastencodes). Da die Hardware keine weiteren Eingabe- oder Ausgabeeinheiten besitzt, kann sie diskret in einer Zimmerecke verschwinden. Der TSOP1736-Empfänger (in Verbindung mit meiner Fernbedienung) ist so empfangsstark, daß eine direkte Sichtverbindung nicht notwendig ist.

Für die Bedienerführung habe ich mir folgendes Menüschema überlegt und implementiert:

Durch drücken der <- (Zurücktaste, hier: "reserved") verzweigt die Statemaschine immer wieder in ihren Anfangszustand. So kann jederzeit ein angefangener "Pfad" abgebrochen und in eine definierte Ausgangsituation zurückgesprungen werden.

Lesebeispiel: Rolladen Wohnzimmer soll etwas gesenkt werden. Notwendige Tastendrücke:

  • 3 (für Rolläden bewegen)
  • 3 (Rolladen Wohnzimmer)
  • + oder - für Heben oder Senken.
  • <- (Zurücktaste) zum Beenden

Wird in einem Zustand nicht innerhalb einer konfigurierbaren Zeit eine Taste gedrückt, so kann davon ausgegangen werden, daß keine weitere Aktion gewünscht wird. Die Statemschine springt danach wieder in ihren Ausgangszustand (so wird verhindert, daß der Knoten in einem Zustand "hängenbleibt", der ja mangels Ausgabeeinheit vom Benutzer nicht erkannt werden kann).

Verwendete Includefiles: ir.h, ...

 

4.2.1.11 RSte (RolladenSteuerung)

Die Rolladensteuerung wurde für den Buskoppler_v2 entwickelt, weil die normale Zeitschaltuhr (ZSUr) wegen fehlender direkter Eingriffsmöglichkeit für diesen Anwendungszweck zu unflexibel ist.
Die Rolläden sollen im Urlaub oder an Feiertagen nicht zur gewohnten, frühen Zeit hochfahren, sondern erst später. Diese und weitere Einstellungen lassen sich bequem über ein Menüsystem, das von einem 4-Tasten-Cursorblock bedient wird, eingeben.


("nackte" Version der Rolladensteuerung)

Das Menüsystem erklärt sich hier am besten selbst.

 


4.2.2 Includes

Die Includefiles bilden die Grundlage der Knotensoftware. Auf den Funktionen, die in den "Includes" abgelegt sind, basiert die Projektsoftware. Im folgenden werden die einzelnen Include-Files kurz vorgestellt, ihre Funktion umrissen und eventuelle (Software)Schnittstellen beschrieben.

Um die Kompatibilität zu früheren Projekten zu gewährleisten, werden Softwareänderungen, die den Codeumfang erhöhen würden, nur per #ifdef-Anweisung in den Include-Quellcode aufgenommen. Um diese Erweiterungen nutzen zu können, müssen die entsprechenden #define-Konstanten in die projektbezogene Includedatei "DefProjekt.h" aufgenommen werden.

 

4.2.2.1 can.h: grundlegende Buskommunikation

Hier sind die Funktionen zusammengefaßt, die für alle Knoten gelten sollen und die sich auf die Kommunikation mit dem CAN-Bus beziehen.

  • CANLesen, CANSchreiben: Diensteprimitive, Lesen/Schreiben der CAN-Register
  • CANInit: Initialisierung der CAN-Register des CAN-Controllers
  • Empfang: Aufgerufen vom Hauptprogramm zur Erkennung welches MO ein CAN-Telegramm empfangen hat, dann Aufruf des entsprechenden Unterprogrammes im Hauptprogramm (der ProjektSoftware), z.B. MO1Soft. Ausführung im Interrupt 0.
  • Knotenbefehl: Wertet auf MO15 eintreffende Telegramme aus und liefert Rückantworten an die anfragenden Knoten. Siehe Kapitel Knotenbefehle.


4.2.2.2 sendtele.h: Telegrammversand

  • EETelegrammSenden: Versendet vorgefertigte, im EEProm abgelegte Telegramme.
  • CANTelegramm: Versendet per Parameter übergebenes Telegramm. Erwartet ebenso die Übergabe von ID, DLC und RTR-Bit.
  • CANTelegrammIDB0IDB1: Versendet übergebenes Telegramm. IDB0/1 liegen bereits fertig im übergebenen Telegramm vor. (Keine Umrechnung von CAN-ID, DLC, RTR nach IDB0/1 notwendig)
  • ID2IDB0 und ID2IDB1: Umrechnungsfunktionen; errechnet CAN-ID-Byte0 und CAN-ID-Byte1 aus CAN-ID.

 

4.2.2.3 timer.h: TimerInitialisierungen

  • Timer0Init: Initialisiert Timer0 als Millisekunden Timer. Die Timerinterruptroutine muß sich im Hauptprogramm (Projektsoftware) befinden (da diese vom Projekt abhängig ist).
  • Wait_ms: Schleife, die die übergebene Zeit in Millisekunden verstreichen läßt. (Bereich: 0-65535 Millisekunden)
  • Wait_us: Schelife, die die übergebene Zeit in Mikrosekunden verstreichen läßt. (Bereich: 0-65535 Mikrosekunden)
  • Timer_Uptime: (aktivierbar durch #define UPTIME) zählt die Zeit in Minuten, Stunden und Tagen seit Systemstart bzw. den letzten Reset (dient zur Erkennung von unbeabsichtigten Resets (Spannungsschwankungen)). (Neu -2002-06-03)
  • Betriebsstunden_aktualisieren (wird zusammen mit Timer_uptime verwendet und von diesem stündlich aufgerufen): Die Betriebsstunden werden aus dem intEEProm an Adresse 0xFD und 0xFE ausgelesen, um 1 erhöht und wieder zurückgeschrieben. (Neu -2002-06-03)


4.2.2.4 relais.h: Taster und Relais

(erweiterte Beschreibung für v3.x+ - bitte hier klicken).

Routinen: TasterAbfragen, TastLokal
Wertet die angeschlossenen Taster an der CAN-Controller Porterweiterung (Port1) aus (steigende Flanke) und veranlaßt den Telegrammversand bereits vorgefertigter Telegramme (aus dem EEProm). Gleichzeitig werden Relais geschaltet, die am gleichen Knoten angeschlossen sind, da diese leider nicht per CAN-Telegramm erreichbar sind. Einzelheiten siehe Kapitel 3.2.

Routinen: TelegrammRelais[1-4]
Liest eingetroffenes Telegramm aus MO[1-4] aus und schaltet entsprechendes Relais nach übermittelter Anweisung. Dabei sind folgende Kommandos an ein Relais möglich:

ParameterByte:

ParameterByte/ Datenbyte0 (dez.) Bedeutung
0 Relais aus
1 Relais ein
2 Relais um (toggeln)
3 Statusabfrage (siehe folgende Tabelle)


Statusabfrage

Mittels Statusabfrage-Telegramm läßt sich der aktuelle Relaiszustand herausfinden. Dies kann zum Beispiel für PC-Visualisierungen von Interesse sein. Dazu wird ein Paket mit folgendem Format an die CAN-ID des Relais geschickt.

Datenbyte0 Datenbyte1 Datenbyte2 Datenbyte3 Datenbyte4 Bedeutung
3 (dez.) Antw. ID Byte0 Antw. ID Byte1 - - Statusabfrage Relaiszustand

Datenbyte1 und 2 enthält die Adresse (Antwort IDB0 und IDB1) des anfragenden Knotens. Schließlich muß der befragte Knoten wissen an welche Adresse er die Antwort senden soll.

Beispiel: Der PC (repräsentiert durch RS232Applikation mit Knotennummer 2, MO13 -> ID 245 ->IDB0=0x1E, IDB1=0xA8) interessiert sich für den Zustand des Relais Nr. 3 (-> MO3) an Knotennr. 1 (-> ID: 219). Dazu verschickt er ein CAN-Telegramm mit der ID 219 und folgendem Inhalt:
0x03 0x1E 0xA8

Das Antworttelegramm des angesprochenen Relais sieht so aus:

Parameterbyte/
Datenbyte0
Datenbyte1 Datenbyte2 Datenbyte3 Datenbyte 4 Bedeutung
3 (Echo) ID Byte0 ID Byte1 0 0x00 Antwort Relaiszustand: aus
3 (Echo) ID Byte0 ID Byte1 0 0x01 Antwort Relaiszustand: ein

Datenbyte 1 und 2 enthält hier die Adresse (CAN-ID) des Relais. So kann der Empfänger festellen welches Relais gerade geantwortet hat.

Im obigen Beispiel ergäbe sich folgende Antwort:
an CAN-ID 245: 0x03 0x1E 0xA8 0x00 (Relais aus)



4.2.2.5 rolladen.h: spezielle Rolladenroutinen

Telegrammverarbeitung für Rolladen1 (eintreffend auf MO1) und/oder für Rolladen2 (eintreffend auf MO2).
Der Telegramminhalt besteht aus 1 Parameterbyte für die Positionsangabe:

ParameterByte:

0 Rolladen soll komplett offen sein
1-99 Rolladen stellt ensprechnde Position ein
100 Rolladen soll komplett geschlossen sein
127 Rolladen stoppt sofort
255 Statusabfrage (siehe folgende Tabelle)

(Position 0 und 100 kalibrieren gleichzeitig die interne Stellung)

Beispiel 1: Rolladen 1 an Knoten 50 soll in Position 96 fahren (fast geschlossen). Hierzu wird ein Telegramm mit der CAN-ID 1001 und dem einzigen Datenbyte mit dem Wert 0x60 (=96dez.) verschickt.
Beispiel 2: Rolladen 2 an Knoten 50 soll sofort anhalten. Hierzu wird ein Telegramm mit der CAN-ID 1002 und dem Datenbyte 0x7F verschickt.


Statusabfrage

Mittels Statusabfrage-Telegramm läßt sich die aktuelle Rolladenposition und die Zielrolladenposition herausfinden. Dies kann zum Beispiel für PC-Visualisierungen von Interesse sein. Dazu wird ein Paket mit folgendem Format an die CAN-ID des Rolladens geschickt.

ParameterByte/
Datenbyte0
Datenbyte1 Datenbyte2 Datenbyte3 ... Bedeutung
255 AntwortID Byte0 AntwortID Byte1 0   Statusabfrage Momentanposition
255 AntwortID Byte0 AntwortID Byte1 1   Statusabfrage Zielposition

Beispiel: Der PC (repräsentiert durch RS232Applikation mit Knotennummer 2, MO13 -> ID 245 ->IDB0=0x1E, IDB1=0xA8) möchte die Momentanposition des 1.Rolladens an Knoten 50 erfahren (ID=1001). Dazu sendet er ein Paket an den RS232-Knoten nach vorgegebenen Format. Der Inhalt des CAN-Telegramms mit der CAN-ID 1001 sieht dann folgendermaßen aus:
0xFF 0x1E 0xA8 0x00

Der angesprochene CAN-Knoten bzw. die Funktion, die die eintreffenden Telegramme für den Rolladen abarbeitet, antwortet darauf dann nach folgendem Schema:

ParameterByte/
Datenbyte0 (Echo)
Datenbyte1 Datenbyte2 Datenbyte3 Datenbyte 4 Bedeutung
255 ID Byte0 ID Byte1 0 0x<nn> Antwort Momentanposition
255 ID Byte0 ID Byte1 1 0x<nn> Antwort Zielposition

In Datenbyte1 und 2 stehen die Adresse (CAN-ID) des angesprochenen Rolladens. So kann der Empfänger des Telegramms erkennen, von welchem Absender das Telegramm verschickt wurde. Datenbyte 0 und 3 sind nur ein Echo der Anfrage. Datenbyte 4 enthält die geforderten Daten.

Im obigen Beispiel würde die Antwort des angesprochenen Rolladens z.B. so aussehen:
0xFF 0x12 0xC8 0x00 0x32
(Knotennummer: 50 -> ID=150 -> IDB0=0x12, IDB1=0xC8) Datenbyte 4: 0x32 = 50dez. -> Rolladen halb offen

 

4.2.2.6 funktionen.h: diverse Funktionen, z.B. sprintf

Hier sammeln sich diverse Funktionen an, die nirgendwo thematisch passen. Bisher sind in funktionen.h folgende Funktionen zusammengefaßt:

  • sprintf: Eingeschränkte Version von sprintf; es können aus Speicherplatzgründen keine Real-Zahlen ausgegeben werden

 

4.2.2.7 canports.h: entprellte Taster und Tastenmatrix an der CAN-ControllerPorterweiterung

CANPort0Taster/ CANPort1Taster:
Im Gegensatz zu TasterAbfragen aus relais.h, das hardwareentprellte Taster an den Eingängen erwartet, können mit CANPort0Taster/ CANPort1Taster Taster angeschlossen werden, die nicht hardwareentprellt sind. Die Routine erledigt eine Softwareentprellung für eine Prelldauer von 10ms. Wird nach dieser Zeit weiterhin ein Prellen festegestellt, so wird dies der aufrufenden Routine zurückgemeldet, ansonsten wird der Portzustand zurückgeliefert.

MatrixTastatur:
Eine Matrixtastatur (wie in Kapitel 2.4.3 vorgestellt) wird an der CAN-Porterweiterung des CAN-Controllers erwartet. Nacheinander werden alle Taster abgefragt und entprellt, die gedrückte Taste wird zurückgeliefert. Werden mehrere Tasten gleichzeitig gedrückt, so kann dies nicht eindeutig erkannt werden und es wird eine falsche Information zurückgeliefert. Um das zu umgehen müßte die Matrix um Dioden für jede Taste ergänzt werden.

 

4.2.2.8 lcd.h: Betrieb eines LCDs

Die lcd-Routinen erlauben die Ansteuerung eines HD44780-kompatiblen PunktmatrixDisplays. Die Routine LCDInit, die für die Initialisierung des LCDs zuständig ist, ist auf ein 2x16 Zeichen Display ausgelegt.
LCDGotoXY positioniert den Cursor an die Koordinaten x,y. Mit LCDText kann dann dort ein Text angezeigt werden. LCDBefehl erlaubt es im Zusammenspiel mit den vordefinierten Konstanten: DISPLAY_CLEAR, CURSOR_HOME, CURSOR_BLINK, CURSOR_OFF einen entsprechenden Befehl an das Display abzusetzen.
LCDBeleuchtungEin schaltet die Hintergrundbeleuchtung ein. LCDBeleuchtungAus schaltet die Beleuchtung folglich aus. Die Konstante LCDBELEUCHTUNGTIMEOUT_INITWERT beinhaltet den Wert in Sekunden, der vergeht, bis die Hintergrundbeleuchtung wieder abgeschaltet wird. (Muß vom Hauptprogramm-Timerinterrupt-Aufruf unterstütz werden; Beispiel siehe MenS ab v1.12). Eingeschaltet (bzw. Timeoutwert zurückgesetzt) wird die Hintergrundbeleuchtung bei jedem schreibenden Zugriff auf das Display.
Der Anschluß der Hardware ist in Kapitel 2.4 beschrieben.

Neu (2002-05-24): "#define LCDDEFCHAR" erweitert lcd.h um die Funktionalität eigene Zeichen auf dem LC-Display darstellen zu können. Dazu wird die Funktion "LCDDefChar" mit den Parametern für die Nummer des zu definierenden Zeichens (0..7) und der Zeichenkette (bzw. einen Zeiger darauf), die das Zeichen repräsentiert, aufgerufen. Die Software SpezialChar von B.Müller (http://www.mme-berlin.de/avr/indexd.htm) ist zum Zeichnen sehr hilfreich. Die so definierten Zeichen werden dann so: sprintf(Puffer, "%c",CGRAM_CHAR0); in einen String gebracht.

 

4.2.2.9 uart.h: UART-Kommunikation (RS232)

Hauptsächlich kommen hier die Routinen UARTInit und UARTSend zur Anwendung. Ihre Bedeutung erschließt sich aus ihrem Namen. Die Baudrate ist auf 9600,8,N,1 eingestellt.

 

4.2.2.10 ds1820.h: TemperaturSensor DS1820 auslesen

Kommunikationsroutinen zum Datenaustausch mit einem Dallas DS1820 Temperatursensor über das/die 1wire-Protokoll/Anbindung. Die Routinen DS1820_reset, DS1820_write_byte, DS1820_readbyte, DS1820_convert_temp und DS1820_get_temp sind im Datenblatt zum DS1820 beschrieben und weitgehend selbsterklärend. Der Anschluß des Sensors ist an PortC4 des AVRs vorgesehen, siehe Kapitel 2.4.4.

 

4.2.2.11 I2C.h: I2C-Bus Steuerung und Dienstprimitive

Die Anbindung des I2C Busses an den AVR wird, wie in Kap. 2.4.6 beschrieben, durchgeführt. I2C.h beinhaltet folgende Routinen:

  • I2CInit: konfiguriert die AVR I/O-Ports
  • I2CWriteByte: Taktet ein Byte auf die SDA-Leitung
  • I2CReadByte: Liest Byte von SDA
  • I2CWriteAck: Schreibt Ack-Bit auf Bus
  • I2CWriteNAck: Schreibt NAck-Bit auf Bus
  • I2CReadAck: Wertet Ack/NAck von Slave aus
  • I2CWriteSlave: Sendet Datenbyte an Adresse
  • I2CReadSlave: Liest Datenbyte von Adresse

Bemerkung: Die Adresse setzt sich aus den 7 I2C-Adressbits zusammen, allerdings in ihrer eigentlichen Wertigkeit. Diese werden dann noch 1 Bit nach links geschoben und das LSB mit der Lese/Schreibrichtung verodert. (Beispiel: (Basis)-Adresse eines PCF8574 ist somit 0x20, das von der Routine dann auf 0x40 bzw. 0x41 verändert wird )

Diese Funktionen stellen die Diensteprimitive zur Verfügung, auf die von weitergehenden Funktionen aus aufbauenden Includes zurückgegriffen wird.

I2CRead/WriteSlave kann beispielsweise direkt mit einen PCF8574 kommunizieren.

Neu (2002-05-24): Per "#define I2C_400kHz" kann die Busfrequenz auf ca. 400kHz erhöht werden (in DefProjekt.h unterzubringen). Diese Einstellung gilt dann für alle I2C-Slaves. Kann auch nur ein Slave nicht mit der erhöhten SCL-Frequenz umgehen, so darf dieses #define nicht benutzt werden. (24C64 kann mit 400kHz betrieben werden, aber LM75 beispielsweise nicht).

 

4.2.2.12 24C64.h: Anbindung eines I2C Speicherbausteins

Der serielle Speicherbaustein 24C64 (hier: ST24C64; 8kByte Speicherplatz) läßt sich mit Hilfe der Bibliothek 24C64.h beschreiben und auslesen. Alle implementierten Funktionen können dabei auf einen Adreßraum von 64kByte zugreifen. Die Adressierung des genauen Speicherbausteins geschieht in der Routine und muß daher von aufrufenden Programmteilen nicht beachtet werden. Beim Anschluß der Hardware ist darauf zu achten, daß die einzelnen Speicherbausteine in ihrer konfigurierbaren Adresse aufeinanderfolgen. Ist der adressierte Speicherbaustein physikalisch nicht adressierbar (weil er evtl. nicht vorhanden ist), so wird in der globalen Variablen "Fehlernr", der aktuelle Fehler übergeben (Fehlernr = 0: fehlerfrei). Die aufrufende Routine kann diesen dann auswerten. Die Funktionen bauen auf der Bibliothek I2C.h auf.

  • I2C_24C64RandomAccessRead: Liest genau 1 Byte aus dem Adreßraum von 64kByte
  • I2C_24C64WriteByte: Schreibt 1 Byte in den Speicher
  • I2C_24C64Read16Byte: Liest 16 aufeinanderfolgende Speicherzellen aus und überträgt diese in ein geliefertes Feld
  • I2C_24C64Write16Byte: Schreibt die gelieferten 16 Datenbytes aufeinanderfolgend in den Speicher

Die nachfolgend genannten Funktionen werden durch eintreffende Telegramme auf ihren zugewiesenen MOs aktiviert. Die Parameter sind in den Telegrammen codiert:

  • extEEPromSchreiben: Schreibt 4 Bytes an "Adresse" im extEEProm und sendet Bestätigung an Absender.
  • extEEPromLesen: Liest 4 Bytes von "Adresse" aus extEEProm und sendet diese an die gewünschte Adresse.
  • extEEPromLoeschen: Überschreibt alle Speicherstellen mit 0xFF. Eine Bestätigung des Befehlseintreffens wird sofort an den Absender verschickt.

 

 

4.2.2.13 Zeit.h: Aktualisierung der knoteninternen SoftwareUhr

Die Routine DCFZeit wird von eintreffenden Zeittelegrammen (CAN-ID: 50) auf MO13 aktiviert. Die eingetroffenen Zeitinformationen (Uhrzeit, Datum und Wochentag) werden von der knoteninternen Softwareuhr übernommen (Voraussetzung dafür ist natürlich, daß das Hauptprogramm eine solche Softwareuhr bereitstellt). Der Aufbau eines Zeittelegramms sieht (am Beispiel für 3.4.2002 - 19:30:00, Wochentag: 3) so aus:

CAN-ID Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7
50 0xAA Jahr WTag/Monat Tag Stunde Minute Sekunde (Siehe Tabelle unten)
0x06, 0x48 -> ID: 50 0xAA 0x02 0x34 0x03 0x13 = 19 0x1E = 30 0x00 0x01

Aufbau Byte2: (Wochentag<<4 | Monat), d.h. die oberen 4 Bits beschreiben den Wochentag, die unteren 4 beinhalten den Monat.

Bit7 (MSB) ... Bit1 Bit0
(reserviert) ... (reserviert)

0: MEZ (Winterzeit)
1: MESZ (Sommerzeit)

Tabelle: Bedeutung des Byte7 im Zeittelegramm

Wochentag: 1:Mo, 2:Di, 3:Mi, 4:Do, 5:Fr, 6:Sa, 7:So

 

4.2.2.14 ir.h: Dekodierung der eintreffenden IR-Signale

Die hier verwendeten Routinen sind größtenteils von Bray übernommen und nur an wenigen Stellen modifiziert.
Die erste fallende Flanke, die vom IR-Empfänger detektiert wird, löst einen Interrupt0 aus. Dieser sperrt dann weitere Interrupts und startet den vorbereiteten Timer1. Dieser wird zum ersten Mal nach 3111us aufgerufen, danach alle 889us. Hier werden dann die einzelnen eintreffenden Bits ausgewertet und in Variablen (Repeat, Adresse, Command) verpackt, die das Hauptprogramm auswerten kann. Anschließend wird der IR-Interrupt wieder zum Empfang des nächsten IR-Befehls freigegeben.

Ausführliche Beschreibung des RC-5 Codes und dessen Aufbau unter: http://users.pandora.be/nenya/electronics/rc5/index.htm

 

4.2.2.15 PCF8591.h: Anbindung eines I2C AD/DA-Wandlers

Der PCF8591 Baustein (Beschreibung) besitzt 4 AD-Wandler zu je 8 Bit und einen DA-Wandler (8Bit). Bis zu 8 Bausteine dieses Typs können an einem I2C-Bus betrieben werden. Die Basisadresse lautet 0x48, zu dieser wird dann die SlaveNr hinzuaddiert (verodert). Achtung, auch andere Bausteine anderer Typen verwenden diese Basisadresse (z.B. LM75). So können in Summe nur max. 8 Slaves dieser Typen verwendet werden. Der PCF8591 darf nur mit 100kHz (oder weniger) Bustakt gefahren werden. (#define I2C_400kHz darf nicht gesetzt sein.)

Die Bibliothek PCF8591.h stellt diese Funktionen zur Kommunikation mit dem PCF8591 zur Verfügung:

  • I2C_PCF8591Write: Beschreibt PCF8591 der SlaveNr (0..7) mit ControlByte. Bei gesetztem AOEF (AnalogOutputEnableFlag) wird der zuvor übermittelte Analogwert ausgegeben! Achtung, übergebener Analogwert wird erst beim nächsten Schreiben ausgegeben!
  • I2C_PCF8591Read: Liest von PCF8591 mit der SlaveNr (0..7) genau 1 Datenbyte ein (Wert eines AD-Wandlers). Zum Auswählen des AD-Wandlers muß zuvor ein I2C_PCF8591Write ausgeführt werden. Achtung, übergebener Analogwert stammt von letzter Wandlung, nicht von aktueller!

Auch diese Funktionen bauen auf der Bibliothek i2c.c auf. Auf zahlreiche Konstantendefinitionen in PCF8591.h kann dabei zurückgegriffen werden.

Beispiel:
I2C_PCF8591Write(0, PCF8591_CHANNEL2 | ANALOG_OUTPUT_ENABLE, 0);

 

4.2.2.16 lm75.h: Anbindung eines I2C TemperaturSensors

LM75 Eigenschaften: (Beschreibung)

  • Temperaturmeßbereich -55°C bis +125°C (Genauigkeit: 3°C)
  • Temperaturmeßbereich -25°C bis +100°C (Genauigkeit: 2°C)
  • Basisadresse: 0x48 (Achtung, identisch mit PCF8591)
  • nur in SMD-Gehäuse SOP-8 (und MSOP-8) erhältlich
  • 5V-Typen und 3.3V-Typen verfügbar
  • Bustakt max. 100kHz (-> #define I2C_400kHz darf nicht gesetzt sein.)

Die Bibliothek lm75.h stellt diese Funktionen zur Kommunikation mit dem LM75 zur Verfügung:

  • I2C_LM75ReadTemp: Liest aktuelle Temperatur von LM75; SlaveAdresse: 0..7

Die Funktionen zur standalone-Überwachung von Temperaturen und eigenständiges Schalten des O.C.-Ausganges wird (noch) nicht unterstützt.


Zur Abfrage eines Temperaturwertes über CAN-Bus dient folgende Routine:

  • LM75Kommando: Wird von einem eintreffenden Telegramm aktiviert und noch im Interrupt ausgeführt.

Kommandos können sein:

  • TemperaturSenden: (BefehlsByte = 0x00) Liest Temperatur von LM75-Sensor und übersendet ermittelten Wert an die übergebene CAN-ID.
  • ConfigRegisterLesen/Schreiben: noch nicht implementiert!
  • T Hyst, T OS lesen/schreiben: noch nicht implementiert!

Die Telegrammformate zur Kommunikation mit dem TemperaturSensor LM75 finden sich in Kapitel 6.12.