'############################################################################## ' StarLight_Slave.BAS Stand 14.02.2011 ' ------------------- (C) Markus Fulde ' ' Steuerprogramm für Slaveeinheit der StarLight Deckenbeleuchtungselektronik ' ' Das Steuerprogramm verfügt über die folgenden einzelnen Funktions- und ' Teilkomponenten: ' - Mikrocontroller ATmega168 (inkl. ISP, RS232 und Reset) ' - 20 MHz externer Clock ' - RS485-Interface für Kommunikation mit Master ' - Slave-Adresse über 4-Bit DIP-Schalter konfigurierbar ' - Nulldurchgangserkennung mittels Optokoppler für Dimmer ' - Dimmersteuerung mittels optoentkoppeltem IGBT ' - 1-Wire Temperatursensor für Umgebungstemperatur ' - Lichtsteuerung An/Aus über Solid-Sate-Relais ' - Akustischer Signalgeber ' - LED-Anzeigen für Funktionsanzeige ' ' - Funktions- und Debug-Steuerung über RS232 ' ' ' Das Slaveprogramm führt die vom Master empfangenen Kommandos aus und sendet ' entsprechende Antworten/Statubotschaften zum Master zurück. ' Ein Slave verfügt über keine eigene Intelligenz, ist in seiner primären ' Aufgabe ein Phasenabschnittsdimmer, überwacht aber seine Umgebungstemperatur ' und schaltet für sich selbst die Netzspannung an/aus. ' '############################################################################## '------------------------------------------------------------------------------ ' Compilerinstruktionen und Compilerdirektiven '------------------------------------------------------------------------------ $regfile = "m168def.dat" ' Definitionsdatei für ATmega168 laden $crystal = 20000000 ' Quarzfrequenz für 20 MHz festlegen $hwstack = 128 ' HW-Stack auf 128 Bytes erweitern $swstack = 64 ' SW-Stack auf 64 Bytes erweitern $framesize = 80 ' Framesize auf 80 Byte festlegen ' $baud = 38400 ' Baudrate für RS232 auf 38400 Bauf festlegen ' Hinweis: Direktive nicht notwendig da Konfiguration über CONFIG '------------------------------------------------------------------------------ ' Allgemeine Zusatzinformatonen zu Programmbeginn '------------------------------------------------------------------------------ ' ASCII Table (Incomplete) ' Decimal Hex Binary Value Beschreibung ' ------- --- -------- ----- ------------------ ' 000 000 00000000 NUL (Null char.) ' 008 008 00001000 BS (Backspace) ' 009 009 00001001 HT (Horizontal Tab) ' 010 00A 00001010 LF (Line Feed) ' 012 00C 00001100 FF (Form Feed) ' 013 00D 00001101 CR (Carriage Return) ' 032 020 00100000 SPACE (Leerzeichen) ' 048 030 00110000 0 (Beginn der Ziffern) ' 049 031 00110001 1 (..) ' 052 034 00110100 4 (..) ' 065 041 01000001 A (Beginn der Zeichen) ' 066 042 01000010 B (..) ' 067 043 01000011 C (..) ' Hinweis: Im Datenblatt wird die zeit von 750 ms nur in Verbindung mit dem ' parasite power mode genannt. Test in der Praxis haben interessanter Weise ' jedoch ergeben, das auch mit normaler Spannungsversorgung beim DS18S20 Zeiten ' bis 700 ms erreicht werden. Wird zu zeitig ausgelesen liefert der Sensor den ' Fehlercode 10101010 welcher 170 DEZ = 85°C entspricht. Wird dieser Wert bei ' erstmaligem Convert T ausgelesen ist dies ein Zeichen dafür, dass der Sensor ' den Konvertierungsvorgang noch nicht abgeschlossen hat. '------------------------------------------------------------------------------ ' Definition von Ressourcen '------------------------------------------------------------------------------ ' ----- DIM: Dimmer ----- ' Nulldurchgangserkennung Nulldurchgang_pin Alias Pind.2 ' GPIO für Nulldurchgangserkennung (für DDR oder Input) Nulldurchgang Alias Portd.2 ' GPIO für Nulldurchgangserkennung (für Output oder PullUp) ' IGBT Steuerung Igbt_pin Alias Pind.4 ' GPIO für IGBT-Steuerleitung (für DDR oder Input) Igbt Alias Portd.4 ' GPIO für IGBT-Steuerleitung (für Output oder PullUp) ' Power Steuerung von Solid-State-Relais Powerrelais_pin Alias Pinc.5 ' GPIO für SSR-Steuerleitung (für DDR oder Input) Powerrelais Alias Portc.5 ' GPIO für SSR-Steuerleitung (für Output oder PullUp) ' ----- LED's ----- ' Übertemperatur-LED Temp_led_pin Alias Pind.3 ' GPIO für Übertemperatur-LED (für DDR oder Input) Temp_led Alias Portd.3 ' GPIO für Übertemperatur-LED (für Output oder PullUp) Alive_pin Alias Pinc.4 ' GPIO für Alive-LED (für DDR oder Input) Alive Alias Portc.4 ' GPIO für Alive-LED (für Output oder Pullup) ' ----- Steuerleitungen für RS485-Baustein ----- ' DE = DataEnable für Senden Rs485_de_pin Alias Pind.5 ' GPIO für DE (für DDR oder Input) Rs485_de Alias Portd.5 ' GPIO für DE (für Output oder Pullup) ' RE = ReceiveEnable für Empfangen Rs485_re_pin Alias Pind.6 ' GPIO für RE (für DDR oder Input) Rs485_re Alias Portd.6 ' GPIO für RE (für Output oder Pullup) ' ----- Soundausgabe ----- ' Piezo Piezo_pin Alias Pind.7 ' GPIO für Soundausgabe (für DDR oder Input) Piezo Alias Portd.7 ' GPIO für Soundausgabe (für Output oder PullUp) ' ----- DS1820: 1Wire-Interface DS18S20 1wire_port Alias Portb.2 ' 1Wire-Interface für Temperatursensor ' ----- Adressleitungen für Dipschalter ----- ' Adr0 Adresse0_pin Alias Pinc.0 ' GPIO für Adr0 (für DDR oder Input) Adresse0 Alias Portc.0 ' GPIO für Adr0 (für Output oder Pullup) ' Adr1 Adresse1_pin Alias Pinc.1 ' GPIO für Adr1 (für DDR oder Input) Adresse1 Alias Portc.1 ' GPIO für Adr1 (für Output oder Pullup) ' Adr2 Adresse2_pin Alias Pinc.2 ' GPIO für Adr2 (für DDR oder Input) Adresse2 Alias Portc.2 ' GPIO für Adr2 (für Output oder Pullup) ' Adr3 Adresse3_pin Alias Pinc.3 ' GPIO für Adr3 (für DDR oder Input) Adresse3 Alias Portc.3 ' GPIO für Adr3 (für Output oder Pullup) ' Adressnibble Adresse_port Alias Pinc ' Port für die Adressschaltung '------------------------------------------------------------------------------ ' Definition von Konstaten '------------------------------------------------------------------------------ ' ----- Für Testumgebung bzw. Traceausgaben ----- Const Main_testmodus = 0 ' Flag für Testmodus Allgemeinsystem Const System_testmodus = 0 ' Testmodus zum Abfackeln aller Funktionen vor Systemstart Const Temp_testmodus = 0 ' Flag für Testmodus Temperaturüberwachung Const Dimmer_testmodus = 0 ' Flag für Testmodus Dimmer Const Timer_testmodus = 0 ' Flag für Testmodus Timer Const Rs485_testmodus = 0 ' Flag für Testmodus RS485 Const Eeprom_testmodus = 0 ' Flag für Testmodus EEPROM Const Empfangsueberwachung_testmodus = 0 ' Flag für globale Empfangsüberwachung mit Timerout ' ----- Allgemeine Systemkonstanten ----- Const Led_aus = 0 Const Led_ein = 1 Const Licht_aus = 0 Const Licht_ein = 1 Const False = 0 Const True = 1 Const Pullup_aus = 0 Const Pullup_ein = 1 ' Zeitvorgabe für Sekunden-Timer Const Timervorgabe = 46005 ' Timer von 1 Sekunden (SekundenTick) ' Zeitvorgabe für Receive-Timeout-Überwachung Const Receive_timeout = 2 ' ----- System-Demo ----- Const Sweep_down = 0 Const Sweep_up = 1 Const Demo_sweep_time = 250 ' 250 ms ' ----- Systemcheck ----- Const Looptime = 100 ' Dauer der Schleifenzeit in ms für Check ' ----- Sound: Akustik-Wiedergabe ----- Const Sound_aus = 0 Const Sound_ein = 1 Const Sound_ein_delay = 100 ' Soundlänge in MS Const Sound_pause_delay = 100 ' Soundpause in MS ' ----- Relais: Hauptrelais-Steuerung ----- Const Relais_aus = 0 Const Relais_ein = 1 ' ----- DIM: Systemkonstanten für das Dimmer-Modul ----- Const Dim_helligkeit_default = 0 Const Dim_helligkeitstabellenwerte = 32 Const Dim_helligkeit_min = 0 Const Dim_helligkeit_max = 32 Const Passiv = 0 Const Aktiv = 255 Const Igbt_aus = 0 Const Igbt_ein = 1 ' ----- DS1820: Temperatursensor ----- Const Ds1820_skip_rom_command = &HCC ' Code für Skip ROM Const Ds1820_convert_t_command = &H44 ' Code für Convert T Const Ds1820_scratchpad_command = &HBE ' Code für Read scratchpad Const Ds1820_delay_time = 750 ' 750ms Wartezeit Const Ds1820_auswertung = 30 ' Default Auswerteintervall in Sekunden Const Ds1820_auswertung_start = 2 ' Default Auswerteintervall in Sekunden Const Uebertemperatur_default = 50 ' Konstante für Übertemperatur ' ----- RS485: Systembus RS485 Interface ----- ' Allgemeines Const Nachrichtenlaenge = 10 ' Länger der gesamtbotschaft in Bytes Const Framelaenge = 5 ' Länger der Nutzdaten Const Masteradresse = &H00 ' Master hat Adresse 0 Const Broadcastadresse = &HFF ' Adresse für alle uns alles (Broadcast) Const Undefined = &HFF ' Platzhalter Const Rs485_send_enable = 1 ' DE ein Const Rs485_send_disable = 0 ' DE aus Const Rs485_receive_enable = 0 ' RE/ ein Const Rs485_receive_disable = 1 ' RE/ aus ' 1 Start + 8 Daten + 1 Stop = 10 Bits ' 10 Bytes pro Übertragung => 100 Bits bei 57600 Baud = 1,7361 ms => 2 ms Const Wait_time = 2 ' Wartezeit in ms für RE ' Kommunikation Master -> Slave Const Cmd_licht_schalten = &H01 ' Steuerwort für Licht schalten Const Cmd_dimmer_schalten = &H02 ' Steuerwort für Dimmer steuern Const Cmd_sound_schalten = &H03 ' Steuerwort für Sound schalten Const Cmd_licht_dimmer_schalten = &H04 ' Steuerwort für Licht schalten und Dimmer steuern Const Cmd_status_abfragen = &H05 ' Steuerwort für Status abfragen Const Cmd_uebertemperatur_setzen = &H06 ' Steuerwort für Übertemperatur setzen Const Cmd_demo_sweep = &H07 ' Steuerwort für Demo-Sweep-Modus ' Kommunikation Slave -> Master Const Resp_ack = &HFF ' Response Acknowledge ' Const Resp_uetemp = &H01 ' Response Übertemperatur Const Resp_status = &H02 ' Response Status ' ----- Internes EEPROM ----- ' Aktuelle EEPROM-Datenstruktur Const Akt_internal_ee_version = &H02 ' Aktuelle EEPROM-Datenstruktur intern '------------------------------------------------------------------------------ ' Definition von Variablen und Datentypen '------------------------------------------------------------------------------ ' Bemerkung: ' Die Betiebszustände des Dimmers können über die Variablen ' - Free_running_flag ' - Dim_helligkeitsstufe ' abgefragt werden. ' ----- Temporäre Hilfsvariablen ----- Dim Temp_byte_1 As Byte ' Temporäre Byte Variable 1 Dim Temp_byte_2 As Byte ' Temporäre Byte Variable 2 Dim Temp_byte_3 As Byte ' Temporäre Byte Variable 3 Dim Temp_word_1 As Word ' Temporäre Word Variable 1 Dim Temp_word_2 As Word ' Temporäre Word Variable 2 Dim Temp_word_3 As Word ' Temporäre Word Variable 3 Dim Temp_single_1 As Single ' Temporäre Single Variable 1 Dim Temp_single_2 As Single ' Temporäre Single Variable 2 Dim Temp_single_3 As Single ' Temporäre Single Variable 3 ' ----- Variable für SecTick Scheduler ----- Dim Timercounter As Word ' Scheduler-Variable ' ----- Variablen für globale Receive Timeout Überwachung Dim Receive_timeout_counter As Word ' Vaiable für Counter Dim Receive_timeout_flag As Byte ' Flag für Counter-Überwachung ' ----- Variablen für Dimmer ----- Dim Igbt_schaltzeitpunkte(32) As Byte ' Array für Schaltzeitpunkt Dim Dim_helligkeitsstufe As Byte ' Helligkeitsstufe Dim Dim_index_counter As Byte ' Helligkeitsindex Dim Free_running_flag As Byte ' Dimmerbetrieb Dim Lichtflag As Byte ' Flag of Licht eingeschaltet oder aus ' ----- DS1820: Temperatursensor ----- Dim Ds1820_device_count As Byte ' Variable für Anzahl aller Devices auf 1Wire Dim Ds1820_rom_code(8) As Byte ' Variable für 64-Bit Lasered ROm Code Dim Ds1820_error_flag As Byte ' Globale Variable für Fehlermeldungen Dim Ds1820_scratchpad(9) As Byte ' Varible für Scratchpad Dim Ds1820_messwert As Integer ' Globale Variable für Integer-Messert Dim Ds1820_temperatur As Byte ' Gloable Temperatur zum Casten Dim Ds1820_erfassungs_counter As Word ' Globaler Zähler für Windauswertung Dim Flag_uebertemperatur As Byte ' Flag für Übertemperatur Dim Uebertemperatur As Byte ' Globale Variable für Übertemperatur ' ----- Variable für RS485 Slave-Adresse ----- ' Algemeines Dim Rs485_slaveadresse As Byte ' Slave-Adresse des Dimmers Dim Rs485_broadcastflag As Byte ' Flag für broadcast-Botschaft ' RS485: Globale Sendestruktur Dim Tx_zieladresse As Byte ' Senden: Zieladresse Dim Tx_quelladresse As Byte ' Senden: Quelladresse Dim Tx_framelength As Byte ' Senden: Datenlänge Dim Tx_kommando As Byte ' Senden: Kommando Dim Tx_licht As Byte ' Senden: Datum Licht Dim Tx_dimmstufe As Byte ' Senden: Datum Dimmer Dim Tx_temperatur As Byte ' Senden: Temperatur Dim Tx_sound As Byte ' Senden: Datum Sound Dim Tx_checksumme As Word ' Senden: Cheksumme Dim Tx_buffer(nachrichtenlaenge) As Byte At Tx_zieladresse Overlay ' Overlay über Datenstruktur Dim Tx_bufferindex As Byte ' Sende-Zeiger Dim Rs485_send_request As Byte ' Flag Sendeaufforderung ' RS485: Globale Empfangsstruktur Dim Rx_zieladresse As Byte ' Empfangen: Zieladresse Dim Rx_quelladresse As Byte ' Empfangen: Quelladresse Dim Rx_framelength As Byte ' Empfangen: Datenlänge Dim Rx_kommando As Byte ' Empfangen: Kommando Dim Rx_licht As Byte ' Empfangen: Datum Licht Dim Rx_dimmstufe As Byte ' Empfangen: Datum Dimmer Dim Rx_temperatur As Byte ' Empfangen: Temperatur Dim Rx_sound As Byte ' Empfangen: Datum Sound Dim Rx_checksumme As Word ' Empfangen: Checksumm Dim Rx_buffer(nachrichtenlaenge) As Byte At Rx_zieladresse Overlay ' Overlay über Datenstruktur Dim Rx_bufferindex As Byte ' Empfangs-Zeiger Dim Rs485_data_received As Byte ' Flag Empfangsindikator ' ----- Variablen für Soundausgabe ----- Dim Soundflag As Byte ' Flag für Soundausgabe ' ----- EEPROM Datenstrukturen und persistente Datenhaltung ----- ' EE: EEPROM Datenstruktur internes EEPROM - Setting-Daten Dim Ee_data_version_intern As Eram Byte At &H0000 ' Speicherstelle für Datenversion Dim Ee_data_temperature As Eram Byte At &H0001 ' Speicherstelle für Temperaturschwelle '------------------------------------------------------------------------------ ' Konfiguration und Basiseinstellungen (Projekt und Testumgebung) '------------------------------------------------------------------------------ ' --------------------------------- CONFIG ------------------------------------ ' ----- RS232 ----- ' Hardware RS232 konfigurieren = interne RS232 ' Serialport für RS485 Systeminterface Config Com1 = 57600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0 Config Serialin = Buffered , Size = 254 Config Serialout = Buffered , Size = 254 ' Serialport für RS485 Systeminterface Open "com1:" For Binary As #1 ' Software RS232 Kanal 2 und 3 konfigurieren = externe RS232 ' Anschluss an Mega168 über PORTB.0 für RxD und PORTB.1 für TxD. ' Achtung: Tracesausgaben zum PC erfolgen über SW-RS232. Die HW-RS232 wird zur ' Kommunikation mit RS485-Bus verwendet ' Öffnen eines Transmit-Kanals (#2) für Ausgaben Open "comb.1:38400,8,n,1" For Output As #2 ' Öffnen eines Receive-Kanals (#3) für Eingaben Open "comb.0:38400,8,n,1 " For Input As #3 ' ----- Konfiguration 1-Wire-Interface ----- Config 1wire = 1wire_port ' Konfiguration 1-Wire-Interface ' ----- Timer ----- ' Konfiguration eines Timers für 1 Sekunden Timer-Tick (Scheduler und Alive) Config Timer1 = Timer , Prescale = 1024 ' Timer 1 verwenden On Timer1 Sekunden_tick ' Interrupt Routine Timer1 = Timervorgabe Enable Timer1 ' Interrupt für Sekunden-Tack ' ----- Konfiguration Dimmer ----- ' DIM: Interrupt für Nulldurchgangserkennung konfigurieren Gosub Dimmer_konfig ' INT0 so konfiguriert das Trigger bei steigender Flanke Config Int0 = Rising ' Springe zur Interrupt-Routine Dimmer_irq On Int0 Dimmer_null_irq Enable Int0 ' Interrupt5 freigeben ' Konfiguration Timer2 für Abschaltzeitpunkt IGBT nach Vorgabe bzw. Nulldurchgang Config Timer2 = Timer , Prescale = 1024 On Timer2 Dimmer_triac_irq Enable Timer2 ' ------------------------------- Port's und Pin's ---------------------------- ' ----- LED-Konfigurationen ----- Config Alive_pin = Output Config Temp_led_pin = Output ' ----- Sound-Konfiguration ----- Config Piezo_pin = Output ' ----- Hauptrelais ----- Config Powerrelais_pin = Output ' ----- RS485 ----- ' Adressleitungen für Dipschalter Config Adresse0_pin = Input ' Adresspin als Eingang konfigurieren Config Adresse1_pin = Input ' Adresspin als Eingang konfigurieren Config Adresse2_pin = Input ' Adresspin als Eingang konfigurieren Config Adresse3_pin = Input ' Adresspin als Eingang konfigurieren ' RS485-Steuerleitungen konfigurieren Config Rs485_de_pin = Output ' DataEnable Config Rs485_re_pin = Output ' ReceiveEnable ' ------------------------------ Variablen und Werte -------------------------- ' ----- LED-Konfigurationen ----- Alive = Led_aus ' Alive-LED aus Temp_led = Led_aus ' Übertemperatur LED aus ' ----- Sound-Konfiguration ----- Piezo = Sound_aus ' Sound aus auf Port ausgeben Soundflag = Sound_aus ' Soundflag auf Sound = AUS setzen ' ----- Hauptrelais ----- Powerrelais = Relais_aus ' Powerrelais immer aus Lichtflag = Licht_aus ' Licht immer aus ' ----- Globale Variable für SecTick Scheduler ----- Timercounter = 0 ' Sekunden-Counter auf 0 initialisieren ' ----- Dimmervariablen initialisieren ----- Free_running_flag = Passiv ' Free_Running aktivieren Dim_helligkeitsstufe = Dim_helligkeit_default ' Defaulthelligkeit setzen ' ----- DS18S20 ----- Ds1820_temperatur = 0 ' Zunächst Temperatur auf NULL setzen Flag_uebertemperatur = False ' Flag zur Steuerung des Übertemperatur-Handlings ' ----- RS485 ----- ' Adressleitungen für Dipschalter Adresse0 = Pullup_ein ' Interner PullUp ein Adresse1 = Pullup_ein ' Interner PullUp ein Adresse2 = Pullup_ein ' Interner PullUp ein Adresse3 = Pullup_ein ' Interner PullUp ein ' RS485-Steuerleitungen konfigurieren Rs485_de = Rs485_send_disable ' Treiber default tristate Rs485_re = Rs485_receive_enable ' Treiber immer mithörend ' Sende- und Empfangsstrukturen initialisieren Rx_bufferindex = 1 ' Index auf 1 Tx_bufferindex = 1 ' Index auf 1 Rs485_broadcastflag = False ' Adresstyp zurücksetzen ' Adresse berechnen Rs485_slaveadresse = Adresse_port Rs485_slaveadresse = Rs485_slaveadresse And &B00001111 ' Maske über LOW-Nibble ' ----- Globale Empfangs-Timeout-Überwachung ----- Receive_timeout_counter = 0 ' Counter auf NULL Receive_timeout_flag = False ' Flag auf False ' ----- Variablen für Soundausgabe ----- Soundflag = False '------------------------------------------------------------------------------ ' Und los gehts, hier noch die Restarbeiten '------------------------------------------------------------------------------ ' ---------------------------------- Gosub's ---------------------------------- ' ----- Initialisierung Dimmer ----- ' DIM: Interrupt für Nulldurchgangserkennung konfigurieren Gosub Dimmer_konfig ' ----- DS18S20: Konfiguration Temperatursensor ----- Gosub Ds1820_konfig ' Konfiguration Gosub Ds1820_start_measurement ' Erstmaliges Messen auslösen ' ----- Freigabe aller Interrupts ---- Enable Interrupts ' Damit auch Empfang von Daten über Buffer ' ----- EEPROM ----- ' Initialisierung des internen EEPROM aufrufen und ggf. Traces schreiben Gosub Ee_init_internal_eeprom '-- Timer2 sofort anhalten und erst über SW anstossen Stop Timer2 ' ---------------------------------- Systemtest ------------------------------- ' Falls System_testmodus gesetzt ist wird kurzer System-Check durchlaufen. ' Alle relevanten Funktionen werden einmal angefahren und entsprechender Output ' auf der Trace-Schnittstelle wird erzeugt. #if System_testmodus ' *** Adresseinstellung *** ' Ausgabe der errechneten Slave-Adresse Print #2 , "System_testmodus: Adresse " ; Rs485_slaveadresse ; " erkannt" ' *** LED's *** ' LED's blinken lassen For Temp_byte_1 = 1 To 3 Temp_led = Led_ein Waitms Looptime ' Wartezeit für Testschleifen Temp_led = Led_aus Waitms Looptime ' Wartezeit für Testschleifen Next Temp_byte_1 ' *** Sound *** ' Piezo piepsen lassen For Temp_byte_1 = 1 To 3 Piezo = Sound_ein Waitms Looptime Piezo = Sound_aus Waitms Looptime Next Temp_byte_1 ' *** Hauptrelais *** ' Hauptspannung einschalten -> LED für Nulldurchgangserkennung sollte leuchten Powerrelais = Relais_ein Lichtflag = Licht_ein ' 5 Sekunden warten bis Dimmer einsetzt Wait 5 ' *** Dimmer *** ' Dimmer einschalten Gosub Dimmer_ein ' Dimmer langsam von 1 bis 32 hochfahren For Temp_byte_1 = 1 To 31 Step 1 ' Dimmerhelligkeit setzen Dim_helligkeitsstufe = Temp_byte_1 Waitms Looptime ' Wartezeit für Testschleifen Next Temp_byte_1 ' Dimmer langsam von 32 bis 1 abdimmen For Temp_byte_1 = 31 To 1 Step -1 ' Dimmerhelligkeit setzen Dim_helligkeitsstufe = Temp_byte_1 Waitms Looptime ' Wartezeit für Testschleifen Next Temp_byte_1 ' Grobe Schritte dafür lange an Dim_helligkeitsstufe = 10 Wait 5 Dim_helligkeitsstufe = 20 Wait 5 Dim_helligkeitsstufe = 30 Wait 5 ' Dimmer abschalten Gosub Dimmer_aus ' Dimmer korrekt initialisieren Dim_helligkeitsstufe = Dim_helligkeit_default ' Hauptspannung wieder abschalten Powerrelais = Relais_aus Lichtflag = Licht_aus ' *** Temperatursensor *** Print #2 , "Funktion: 1Wire-Konfiguration auslesen und ausgeben" Gosub Ds1820_konfig_detect Print #2 , "Funktion: DS18S20 Teperaturmessung" ' Warten bis Temperatur konvertiert Waitms Ds1820_delay_time Gosub Ds1820_measurement Print #2 , "Gemessene Temperatur : " ; Ds1820_temperatur Print #2 , "" ' Leerzeile ausgeben ' *** RS485 Kommunikation *** ' Auf einen Test der RS485 Kommunikation wird verzichtet da er das Gesamtsystem ' durch unmotiviertes Senden von Bytes stören kann. #endif ' Ende Systemtest ' ----- Scheduler noch korrekt setzen und los ----- ' Daten für Temperaturüberwachung setzen Ds1820_erfassungs_counter = Timercounter + Ds1820_auswertung_start ' ############################################################################# ' ' Hauptprogramm ConvCtrl ' ' ############################################################################# ' ---------------------------------------------- ' ----- Hier ist die Programmhauptschleife ----- ' ---------------------------------------------- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print #2 , "** OK, let's GO **" #endif Clear Serialin ' Rx-Buffer löschen Clear Serialout ' Tx-Buffer löschen Do ' RS485 Buffer auf Empfang prüfen Gosub Rs485_receive_check ' Wurde ein gültiges Kommando empfangen? If Rs485_data_received = True Then ' JA ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Mainloop - Datenpaket empfangen" #endif ' Datenpaket prozessieren Gosub Slave_verarbeitung End If ' Empfangquittierung ' RS485 Sendeauftrag prüfen If Rs485_send_request = True Then ' JA, Senderequest vorhanden, Datenpaket senden ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Mainloop - Daten sollen gesendet werden" #endif ' Daten senden Gosub Rs485_send End If ' Sendeauftrag ' ===== SW Timer Scheduler ===== Gosub Scheduler Loop ' Hauptschleife '## End Hauptprogramm ######################################################### '****************************************************************************** ' Interruptroutinen '****************************************************************************** '------------------------------------------------------------------------------ ' Interrupt-Service-Routine (Timer1): Sekunden_tick ' Routine zur Auswertung des Timer Interrupts '------------------------------------------------------------------------------ Sekunden_tick: ' ----- Programmcode ----- Incr Timercounter ' Timercounter erhöhen Timer1 = Timervorgabe ' Timer neu laden ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Timer_testmodus Print #2 , Timercounter #endif ' Alive-LED toggeln lassen Toggle Alive ' Prüfen ob Übertemperatur vorliegt If Flag_uebertemperatur = True Then ' JA -> Übertemperatur -> dann piepsen und blinken Toggle Piezo Toggle Temp_led End If ' Übertemperatur Return '-- End Sekunden_tick -------------------------------------------------------- '------------------------------------------------------------------------------ ' Interrupt-Service-Routine (INT5): Dimmer_null_irq ' Routine zur Nulldurchgangserkennung des Sinussignals '------------------------------------------------------------------------------ Dimmer_null_irq: ' ----- Programmcode ----- ' In dieser IRQ-Routine wird wegen Geschwindigkeit auf Ausgaben verzichtet If Free_running_flag = Aktiv Then ' IGBT einschalten Igbt = Igbt_ein ' Ablauftimer für Phasenabschnitt starten Start Timer2 Timer2 = Igbt_schaltzeitpunkte(dim_helligkeitsstufe) End If ' Free_running_flag Return '-- End Dimmer_null_irq ------------------------------------------------------- '------------------------------------------------------------------------------ ' Interrupt-Service-Routine (Timer0): Dimmer_triac_irq ' Routine zum Zünden des TRIAC '------------------------------------------------------------------------------ Dimmer_triac_irq: ' ----- Programmcode ----- ' Ablauftimer für Phasenabschnitt stoppen Stop Timer2 ' IGBT abschalten Igbt = Igbt_aus Return '-- End Dimmer_triac_irq ------------------------------------------------------ '****************************************************************************** ' GOSubroutinen '****************************************************************************** ' *********** ' * EEPROM * ' *********** '------------------------------------------------------------------------------ ' EE-Gosubroutine: Ee_init_internal_eeprom ' Subroutine überprüft die Datenkonsitenz aufgrund des verwendeten Versions- ' Index und führt ggf. eine Grundinitialisierung der Datenstrukturen durch. '------------------------------------------------------------------------------ Ee_init_internal_eeprom: ' ----- Programmcode ----- ' Wenn Konstante gesetzt Trace Output schreiben #if Eeprom_testmodus ' Trace Print #2 , "Enter Ee_init_internal_eeprom" #endif ' Trace ' Zur Vollständigkeit hier nochmals die Datenstruktur der internen Daten ' EE: EEPROM Datenstruktur internes EEPROM - Setting-Daten ' Dim Ee_data_version_intern As Eram Byte At &H0000 ' Speicherstelle für Datenversion ' Dim Ee_data_temperature As Eram Byte At &H0001 ' Speicherstelle für Temperaturschwelle ' Aktuelle Datenversion des internen EEPROM lesen Temp_byte_1 = Ee_data_version_intern ' Ist die Datenversion korrekt If Temp_byte_1 <> Akt_internal_ee_version Then ' NEIN, aktuelle Daten neu speichern ' Wenn Konstante gesetzt Trace Output schreiben #if Eeprom_testmodus ' Trace Print #2 , "Ee_init_internal_eeprom: Datenversion intern stimmt nicht" Print #2 , "Ee_init_internal_eeprom: Initialisiere internes EEPROM neu!" #endif ' Trace ' Datenstruktur internes EEPROM entspricht nicht dem aktuellen Stand ' => Datenstruktur neu anlegen bzw. neue Defaultwerte setzen. Ee_data_version_intern = Akt_internal_ee_version Ee_data_temperature = Uebertemperatur_default End If ' Datenversion? ' Wenn Konstante gesetzt Trace Output schreiben #if Eeprom_testmodus ' Trace Print #2 , "Ee_init_internal_eeprom: Setting-Daten internes EEPROM:" ' Wert 01 Temp_byte_1 = Ee_data_version_intern Print #2 , "Version Datenstruktur : " ; Hex(temp_byte_1) ' Wert 02 Temp_byte_1 = Ee_data_temperature Print #2 , "Einstellung Uebertemperatur : " ; Hex(temp_byte_1) #endif ' Trace ' Übergabe der Daten in gloabel Arbeitsvariablen Uebertemperatur = Ee_data_temperature Return '-- End Ee_init_internal_eeprom ----------------------------------------------- ' ********** ' * Dimmer * ' ********** '------------------------------------------------------------------------------ ' DIM - Gosub-Routine: Dimmer_konfig ' Subroutine zur Konfiguration des Dimemrs '------------------------------------------------------------------------------ Dimmer_konfig: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Dimmer_testmodus Print #2 , "Enter Dimmer_konfig" #endif ' PortD.2 als Eingang mit aktivem PullUp konfigurieren Config Nulldurchgang_pin = Input Nulldurchgang = Pullup_ein ' PortD.4 als Ausgang definieren und IGBT abschalten Config Igbt_pin = Output Igbt = Igbt_aus ' Der Interrupt selbst kann nicht in der Gosub-Routine initialisiert werden ' sondern muss im Rumpf des Gesamtprogramms initialisiert werden. ' Dimmerhelligkeit auf Default einstellen Dim_helligkeitsstufe = Dim_helligkeit_default ' Triac Zündzeitpunkte aus Tabelle in Datenstruktur laden Restore Igbt_schalttabelle For Dim_index_counter = 1 To Dim_helligkeitstabellenwerte Read Igbt_schaltzeitpunkte(dim_index_counter) ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Dimmer_testmodus Print #2 , "Dimmer_konfig: Zuendwert " ; Dim_index_counter ; " : " ; Igbt_schaltzeitpunkte(dim_index_counter) #endif Next Dim_index_counter Return '-- End Dimmer_konfig --------------------------------------------------------- '------------------------------------------------------------------------------ ' DIM - Gosub-Routine: Dimmer_an ' Subroutine zum Setzen von Parametern für freien Dimmerlauf, gesteuert über ' Nulldurchgangskennung - Dimmer einschalten '------------------------------------------------------------------------------ Dimmer_ein: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Dimmer_testmodus Print #2 , "Enter Dimmer_an" #endif ' Free_runing wird eingeschaltet Free_running_flag = Aktiv ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Dimmer_testmodus Print #2 , "Dimmer_ein: Free Running ist aktiv" #endif Return '-- End Dimmer_an ------------------------------------------------------------- '------------------------------------------------------------------------------ ' DIM - Gosub-Routine: Dimmer_aus ' Subroutine zum Setzen von Parametern für freien Dimmerlauf, gesteuert über ' Nulldurchgangskennung - Dimmer ausschalten '------------------------------------------------------------------------------ Dimmer_aus: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Dimmer_testmodus Print #2 , "Enter Dimmer_aus" #endif ' Free_running wird ausgeschaltet Free_running_flag = Passiv ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Dimmer_testmodus Print #2 , "Dimmer_aus: Free Running ist passiv" #endif Return '-- End Dimmer_aus ------------------------------------------------------------- ' **************************** ' * DS1820: Temperatursensor * ' **************************** '------------------------------------------------------------------------------ ' Ds1820 - Gosub-Routine: Ds1820_konfig ' Funktion konfiguriert den Ds1820 temperatursensor bzw. ermittelt für globale ' Variaben die relevanten Arbeitswerte '------------------------------------------------------------------------------ Ds1820_konfig: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Temp_testmodus Print #2 , "Enter Ds1820_konfig" #endif ' Auslesen der Anzahl aller am 1Wire-Bus vorhandenen Devices Ds1820_device_count = 1wirecount() ' Auslesen des 64-Bit breiten ROM Codes für gefundenes Device in Array Ds1820_rom_code(1) = 1wsearchfirst() Return '-- End Ds1820_konfig --------------------------------------------------------- '------------------------------------------------------------------------------ ' DS1820 - Gosub-Routine: Ds1820_start_measurement ' Funktion startet globale Temperaturmessung für alle Sensoren '------------------------------------------------------------------------------ Ds1820_start_measurement: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Temp_testmodus Print #2 , "Enter Ds1820_start_measurement" #endif ' Gobales Fehlerflag zurücksetzen Ds1820_error_flag = 0 1wreset ' 1Wire Master fährt RESET ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Temp_testmodus Ds1820_error_flag = Err ' Fehlerflag übergeben Print #2 , "Ds1820_start_measurement: Reset-ERR : " ; Ds1820_error_flag #endif ' Alle angeschlossenen DS18S20 zum Messen veranlassen 1wwrite Ds1820_skip_rom_command ' Senden von Skip ROM command 1wwrite Ds1820_convert_t_command ' Convert T Return '-- End Ds1820_start_measurement ---------------------------------------------- '------------------------------------------------------------------------------ ' DS1820 - Gosub-Routine: Ds1820_measurement ' Funktion startet globale Temperaturmessung für alle Sensoren und macht ' Auswertung auf aktiven Sensor '------------------------------------------------------------------------------ Ds1820_measurement: ' ----- Programmcode ----- ' Achtung: ' Aus dieser Routine wurde die Funktion zum Starten der Messung entfernt. ' Zwischen Start und Auswertung benötigt der Chip eine Zeit von ca. 750 ms ' Diese Zeit wir bei normalem Systemstart durch den Scheduler eingehalten. ' Der erste Messwert der Temperatur nach Systemstart ist erst nach Scheduleraufruf ' ca. 5 Sekunden später vorhanden. ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Temp_testmodus Print #2 , "Enter Ds1820_measurement" #endif ' Measurement starten Gosub Ds1820_start_measurement ' Den Sensor auswählen 1wverify Ds1820_rom_code(1) ' Kommando Scratch-Pad aus Sensor auslesen 1wwrite Ds1820_scratchpad_command ' Senden des Lesekommandos ' Scratchpad aus Sensor auslesen Ds1820_scratchpad(1) = 1wread(9) ' CRC Überprüfung und Messert berechnen If Ds1820_scratchpad(9) = Crc8(ds1820_scratchpad(1) , 8) Then ' Messung war erfolgreich Ds1820_messwert = Makeint(ds1820_scratchpad(1) , Ds1820_scratchpad(2)) ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Temp_testmodus Print #2 , "Ds1820_measurement: CRC OK, Messwert plausibel" Print #2 , "Ds1820_measurement: Integerwert : " ; Ds1820_messwert #endif Else ' Messwert erfassen ' Es ist ein CRC Fehler aufgetreten ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Temp_testmodus Print #2 , "Ds1820_measurement: CRC Fehler bei Messwert aufgetreten" #endif Ds1820_messwert = &HFFCE ' Temperaturwert auf -25°C als Fehlerkennzeichnung End If ' Fehlerbehandlung Temp_single_1 = Ds1820_messwert ' Temperatur auslesen und aufrunden Temp_single_1 = Temp_single_1 * 0.5 Ds1820_temperatur = Temp_single_1 ' Temperatur auf Byte casten #if Temp_testmodus Print #2 , "Ds1820_measurement: Temperaturwert : " ; Ds1820_temperatur ; " {248}C" #endif Return '-- End Ds1820_measurement ---------------------------------------------------- '------------------------------------------------------------------------------ ' DS1820 - Gosub-Routine: Ds1820_konfig_detect ' Funktion liest alle relevanten und verfügbaren 1-Wire Konfigurationsinfor- ' mationen aus und gibt diese aus '------------------------------------------------------------------------------ Ds1820_konfig_detect: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Temp_testmodus Print #2 , "Enter Ds1820_konfig_detect" #endif ' Ausgabe der Anzahl aller am 1Wire-Bus vorhandenen Devices Print #2 , "Ds1820_konfig_detect: Anzahl 1Wire-Devices: " ; Ds1820_device_count ' Überprüfen ob empfangener Code gemäß CRC korrekt Temp_byte_1 = Crc8(ds1820_rom_code(1) , 7 ) If Ds1820_rom_code(8) = Temp_byte_1 Then Print #2 , "Ds1820_konfig_detect: CRC des empfangenen ROM-Codes OK" ' Empfangenen Bytes in Hex ausgeben Print #2 , "Ds1820_konfig_detect: ROM-Code : " ; For Temp_byte_2 = 8 To 1 Step -1 Print #2 , Hex(ds1820_rom_code(temp_byte_2)) ; " " ; Next Temp_byte_2 Print #2 , "" Else ' Konfiguration ausgeben Print #2 , "Ds1820_konfig_detect: CRC des empfangenen ROM-Codes FALSCH" End If ' Fehlerbehandlung Return '-- End Ds1820_konfig_detect -------------------------------------------------- ' ******************* ' * RS485 Systembus * ' ******************* '------------------------------------------------------------------------------ ' Gosub-Routine: Rs485_receive_check ' Routine überprüft ob im Empfangsbuffer Zeichen vorliegen, liest diese und ' baut die Empfangsstruktur auf. Danach wird ein Flag gesetzt, dass eine ' Botschafft erfolgreich empfangen wurde. ' Das Empfangen neuer Botschaften ist über eine Sempahore verriegelt. Erst ' wenn die Empfangene Botschaft verarbeitet ist, wird der Empfang einer neuen ' Botschaft zugelassen. '------------------------------------------------------------------------------ Rs485_receive_check: ' ----- Programmcode ----- ' Prüfen ob noch ein Datenpaket auf Verarbeitung wartet If Rs485_data_received = False Then ' NEIN, es wartet kein Datenpaket mehr auf Verarbeitung, ' die neuen Daten können empfangen werden ' Prüfen ob eib Zeichen im Empfangsbuffer wartet If Ischarwaiting(#1) <> 0 Then ' JA, es wartet ein Zeichen ' Prüfen ob Zeichen erstes Zeichen ist, wenn JA dann Überwachung starten If Rx_bufferindex = 1 Then ' JA Rx_bufferindex ist 1, damit wurde noch kein Zeichen empfangen ' Nun Timer aufziehen für Überwachung des Empfangs und Flag setzen Receive_timeout_flag = True ' Timeout aktvieren Receive_timeout_counter = Timercounter + Receive_timeout ' ggf. Trace ausgeben #if Empfangsueberwachung_testmodus Print #2 , "Rs485_receive_check: Starte Receive-Ueberwachung" #endif End If ' Erstes Zeichen empfangen ' Zeichen in RF-RX-Buffer einlesen Rx_buffer(rx_bufferindex) = Inkey(#1) Incr Rx_bufferindex ' Prüfen ob ausreichende Anzahl von Bytes empfangen If Rx_bufferindex > Nachrichtenlaenge Then ' Timerüberachung deaktivieren 'Receive_timeout_flag = False 'Alle Datenfelder komplett empfangen Rx_bufferindex = 1 'Index zurücksetzen ' Prüfung ob Checksumme gültig Temp_word_1 = Crc16(rx_buffer(1) , 8) If Temp_word_1 = Rx_checksumme Then ' JA, Checksumme ist korrekt ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Rs485_receive_check: CRC korrekt!" #endif ' Prüfung ob empfangenes Datenpaket auch für "mich" If Rx_zieladresse = Rs485_slaveadresse Or Rx_zieladresse = Broadcastadresse Then ' JA, ich bin gemeint ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Rs485_receive_check:" Print #2 , "Rx_zieladresse : " ; Hex(rx_zieladresse) Print #2 , "Rx_quelladresse : " ; Hex(rx_quelladresse) Print #2 , "Rx_framelength : " ; Hex(rx_framelength) Print #2 , "Rx_kommando : " ; Hex(rx_kommando) Print #2 , "Rx_licht : " ; Hex(rx_licht) Print #2 , "Rx_dimmstufe : " ; Hex(rx_dimmstufe) Print #2 , "Rx_temperatur : " ; Hex(rx_temperatur) Print #2 , "Rx_sound : " ; Hex(rx_sound) Print #2 , "Rx_checksumme : " ; Hex(rx_checksumme) Print #2 , " " #endif ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Rs485_receive_check: Message für mich!" #endif ' prüfen ob Broadcast If Rx_zieladresse = Broadcastadresse Then #if Rs485_testmodus Print #2 , "Rs485_receive_check: Broadcastmessage -> kein ACK" #endif Rs485_broadcastflag = True Else ' Broadcast Rs485_broadcastflag = False #if Rs485_testmodus Print #2 , "Rs485_receive_check: Keine Broadcastmessage -> sende ACK" #endif End If ' Prüfung auf Broadcast ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Rs485_receive_check: Rx " ; Hex(rx_zieladresse) ; " " ; Hex(rx_quelladresse) ; " " ; Hex(rx_framelength) ; " " ; Hex(rx_kommando) ; " " ; Hex(rx_licht) ; " " ; Hex(rx_dimmstufe) ; " " ; Hex(rx_temperatur) ; " " ; Hex(rx_sound) ; " " ; Hex(rx_checksumme) #endif ' Flag setzen dass Datenpaket empfangen wurde Rs485_data_received = True Else ' Datenpaket für mich ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Rs485_receive_check: CRC falsch!" Print #2 , "Rs485_receive_check: Soll : " ; Hex(temp_word_1) Print #2 , "Rs485_receive_check: Ist : " ; Hex(rx_checksumme) #endif ' Eingangsbuffer und Ausgangsbuffer löschen Clear Serialin Clear Serialout End If ' Ich war nicht gemeint End If ' Checksummenprüfung End If ' Botschaft vollständig End If ' Wartet ein Zeichen? End If ' Verarbeitungssemaphore Return '-- End Rs485_receive_check --------------------------------------------------- '------------------------------------------------------------------------------ ' Gosub-Routine: Rs485_send ' Die Routine sendet die in der Sendestruktur stehenden Daten über RS485 '------------------------------------------------------------------------------ Rs485_send: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Enter Rs485_send" #endif ' Checksumme setzen Tx_checksumme = Crc16(tx_buffer(1) , 8) ' Bytes übertragen Rs485_de = Rs485_send_enable ' Treiber auf Leitung schalten Printbin #1 , Tx_buffer(1) ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Rs485_send: Tx: " ; For Temp_byte_1 = 1 To Nachrichtenlaenge Print #2 , Hex(tx_buffer(temp_byte_1)) ; " " ; Next Temp_byte_1 Print #2 , " *" #endif Waitms Wait_time ' warten bis Datenübertragung beendet Rs485_de = Rs485_send_disable ' Treiber von Leitung nehmen ' Semaphore für das Senden zurücksetzen und erneutes Senden zulassen Rs485_send_request = False Return '-- End Rs485_send ----------------------------------------------------------- '------------------------------------------------------------------------------ ' Gosub-Routine: Rs485_ack_send ' Die Routine sendet ein Acknowledge als Quittierung '------------------------------------------------------------------------------ Rs485_ack_send: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Enter Rs485_ack_send" #endif ' Status zurück liefern ' Sende-Datenstruktur laden Tx_zieladresse = Masteradresse Tx_quelladresse = Rs485_slaveadresse Tx_framelength = Framelaenge Tx_kommando = Resp_ack Tx_licht = Free_running_flag Tx_dimmstufe = Dim_helligkeitsstufe Tx_temperatur = Ds1820_temperatur Tx_sound = Soundflag #if Rs485_testmodus Print #2 , "Rs485_ack_send:" Print #2 , "Tx_zieladresse : " ; Hex(tx_zieladresse) Print #2 , "Tx_quelladresse : " ; Hex(tx_quelladresse) Print #2 , "Tx_framelength : " ; Hex(tx_framelength) Print #2 , "Tx_kommando : " ; Hex(tx_kommando) Print #2 , "Tx_licht : " ; Hex(tx_licht) Print #2 , "Tx_dimmstufe : " ; Hex(tx_dimmstufe) Print #2 , "Tx_temperatur : " ; Hex(tx_temperatur) Print #2 , "Tx_sound : " ; Hex(tx_sound) #endif ' Sendeanforderung setzen Rs485_send_request = True Return '-- End Rs485_ack_send -------------------------------------------------------- ' ********* ' * Sound * ' ********* '------------------------------------------------------------------------------ ' Sound - Gosub-Routine: Sound_one_beep ' Routine gibt einen einzelnen Beep aus '------------------------------------------------------------------------------ Sound_one_beep: ' ----- Programmcode ----- ' 1x Peep ausgeben. Peepdauer wird über Konstante gesteuert Piezo = Sound_ein Waitms Sound_ein_delay Piezo = Sound_aus Return '-- End Sound_one_beep -------------------------------------------------------- '------------------------------------------------------------------------------ ' Sound - Gosub-Routine: Sound_double_beep ' Routine gibt einen zwei Beep's aus '------------------------------------------------------------------------------ Sound_double_beep: ' ----- Programmcode ----- ' 2x Peep ausgeben. Peepdauer wird über Konstante gesteuert Piezo = Sound_ein Waitms Sound_ein_delay Piezo = Sound_aus Waitms Sound_pause_delay Piezo = Sound_ein Waitms Sound_ein_delay Piezo = Sound_aus Return '-- End Sound_double_beep ----------------------------------------------------- ' ******************* ' * Common routines * ' ******************* '------------------------------------------------------------------------------ ' Gosub-Routine: Slave_verarbeitung ' Hier werden die via RS485 empfangenen Daten verarbeitet '------------------------------------------------------------------------------ Slave_verarbeitung: ' ----- Programmcode ----- ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Rs485_testmodus Print #2 , "Slave_verarbeitung" #endif ' Übersicht über Verarbeitungstasks ' Task 1 = Cmd_licht_schalten ' Task 2 = Cmd_dimmer_schalten ' Task 3 = Cmd_sound_schalten ' Task 4 = Cmd_licht_dimmer_schalten (alles inklusive) ' Task 5 = Cmd_status_abfragen ' Task 6 = Cmd_uebertemperatur_setzen ' Taks 7 = Cmd_demo_sweep Select Case Rx_kommando ' [ *** Task 1 = Cmd_licht_schalten *** ] Case Cmd_licht_schalten: ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print #2 , "Slave_verarbeitung: Cmd_licht_schalten" #endif Select Case Rx_licht Case Licht_aus: ' Dimmer abschalten Gosub Dimmer_aus ' Relais abschalten Powerrelais = Relais_aus Lichtflag = Licht_aus ' ggf. Ausgabesound erzeugen If Soundflag = Sound_ein Then ' Soundflag gesetzt, darum Doppel-Beep ausgeben Gosub Sound_double_beep End If ' Soundprüfung Case Licht_ein: ' Relais einschalten Powerrelais = Relais_ein Lichtflag = Licht_ein ' Dimmer einschalten Gosub Dimmer_ein ' ggf. Ausgabesound erzeugen If Soundflag = Sound_ein Then ' Soundflag gesetzt, darum Beep ausgeben Gosub Sound_one_beep End If ' Soundprüfung End Select ' Auswertung Licht ' Acknowledge senden If Rs485_broadcastflag = False Then ' Nur im Fall das es keine Broadcast-Botschaft war ACK senden Gosub Rs485_ack_send End If ' Acknowledge ' [ *** *** ] ' [ *** Task 2 = Cmd_dimmer_schalten *** ] Case Cmd_dimmer_schalten: ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print #2 , "Slave_verarbeitung: Cmd_dimmer_schalten" #endif ' Aktuelle Variable für Helligkeitsstufe setzen Dim_helligkeitsstufe = Rx_dimmstufe ' Acknowledge senden If Rs485_broadcastflag = False Then ' Nur im Fall das es keine Broadcast-Botschaft war ACK senden Gosub Rs485_ack_send End If ' Acknowledge ' [ *** *** ] ' [ *** Task 3 = Cmd_sound_schalten *** ] Case Cmd_sound_schalten: ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print #2 , "Slave_verarbeitung: Cmd_sound_schalten" #endif ' Aktuelle Variable für Soundausgabe setzten Soundflag = Rx_sound ' Acknowledge senden If Rs485_broadcastflag = False Then ' Nur im Fall das es keine Broadcast-Botschaft war ACK senden Gosub Rs485_ack_send End If ' Acknowledge ' [ *** *** ] ' [ *** Task 4 = Cmd_licht_dimmer_schalten (alles inklusive) *** ] Case Cmd_licht_dimmer_schalten: ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print #2 , "Slave_verarbeitung: Cmd_licht_dimmer_schalten" #endif ' Aktuelle Variable für Helligkeitsstufe setzen Dim_helligkeitsstufe = Rx_dimmstufe ' Licht schalten Select Case Rx_licht Case Licht_aus: ' Dimmer abschalten Gosub Dimmer_aus ' Relais abschalten Powerrelais = Relais_aus Lichtflag = Licht_aus ' ggf. Ausgabesound erzeugen If Soundflag = Sound_ein Then ' Soundflag gesetzt, darum Doppel-Beep ausgeben Gosub Sound_double_beep End If ' Soundprüfung Case Licht_ein: ' Relais einschalten Powerrelais = Relais_ein Lichtflag = Licht_ein ' Dimmer einschalten Gosub Dimmer_ein ' ggf. Ausgabesound erzeugen If Soundflag = Sound_ein Then ' Soundflag gesetzt, darum Beep ausgeben Gosub Sound_one_beep End If ' Soundprüfung End Select ' Auswertung Licht ' Aktuelle Variable für Sound setzten Soundflag = Rx_sound ' Acknowledge senden If Rs485_broadcastflag = False Then ' Nur im Fall das es keine Broadcast-Botschaft war ACK senden Gosub Rs485_ack_send End If ' Acknowledge ' [ *** *** ] ' [ *** Task 5 = Cmd_status_abfragen *** ] Case Cmd_status_abfragen: ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print #2 , "Slave_verarbeitung: Cmd_status_abfragen" #endif ' Status zurück liefern ' Sende-Datenstruktur laden Tx_zieladresse = Masteradresse Tx_quelladresse = Rs485_slaveadresse Tx_framelength = Framelaenge Tx_kommando = Resp_status Tx_licht = Lichtflag Tx_dimmstufe = Dim_helligkeitsstufe Tx_temperatur = Ds1820_temperatur Tx_sound = Soundflag ' Sendeanforderung setzen Rs485_send_request = True ' [ *** *** ] ' [ *** Task 6 = Cmd_uebertemperatur_setzen *** ] Case Cmd_uebertemperatur_setzen: ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print #2 , "Slave_verarbeitung: Cmd_uebertemperatur_setzen" #endif ' Aktuelle Variable für Helligkeitsstufe setzen Uebertemperatur = Rx_temperatur Ee_data_temperature = Uebertemperatur ' ggf. Ausgabesound erzeugen If Soundflag = Sound_ein Then ' Soundflag gesetzt, darum Doppel-Beep ausgeben Gosub Sound_double_beep End If ' Soundprüfung ' Acknowledge senden If Rs485_broadcastflag = False Then ' Nur im Fall das es keine Broadcast-Botschaft war ACK senden Gosub Rs485_ack_send End If ' Acknowledge #if Main_testmodus Print #2 , "Slave_verarbeitung: setze " ; Uebertemperatur Temp_byte_1 = Ee_data_temperature Print #2 , "Slave_verarbeitung: lese " ; Temp_byte_1 #endif ' [ *** *** ] ' [ *** Task 7 = Cmd_demo_sweep *** ] Case Cmd_demo_sweep: Select Case Rx_licht: Case Sweep_down: Temp_byte_1 = Dim_helligkeitsstufe For Temp_byte_2 = Temp_byte_1 To 1 Step -1 Dim_helligkeitsstufe = Temp_byte_2 Waitms Demo_sweep_time Next Temp_byte_2 Case Sweep_up: For Temp_byte_1 = 1 To 31 Dim_helligkeitsstufe = Temp_byte_1 Waitms Demo_sweep_time Next Temp_byte_2 End Select ' [ *** *** ] End Select ' Semaphore wieder auf False setzen um nächstes Datenpaket zu empfangen Rs485_data_received = False Return '-- End Slave_verarbeitung ---------------------------------------------------- '------------------------------------------------------------------------------ ' Gosub-Routine: Scheduler ' Subroutine Abprüfen der in RUNNING befindlichen SW-Timer '------------------------------------------------------------------------------ Scheduler: ' ----- Programmcode ----- ' *** Sequence [01] - Temperaturmessung *** ' Überprüfung ob Temperatur gemessen werden kann und soll If Ds1820_erfassungs_counter = Timercounter Then Gosub Ds1820_measurement ' Scheduler erneut setzen Ds1820_erfassungs_counter = Timercounter + Ds1820_auswertung ' Prüfung auf Übertemperatur If Ds1820_temperatur >= Uebertemperatur Then ' JA; Übertemperatur ' Flag setzen Flag_uebertemperatur = True ' Dimmer abschalten Gosub Dimmer_aus ' Relais abschalten Powerrelais = Relais_aus Else ' Übertemperatur ' Nein, keine Übertemperatur -> Flag auf jeden Fall zurücksetzen Flag_uebertemperatur = False Piezo = Sound_aus Temp_led = Led_aus End If ' Übertemperatur End If ' Ende Temperaturmessung ' *** Sequence [02] - Receive-Timeout-Überwachung *** ' Prüfen, ob Überwachung gemacht werden muss If Receive_timeout_flag = True Then ' JA ' Prüfen ob Timeout abgelaufen If Timercounter > Receive_timeout_counter Then ' JA, Timeout abgelaufen ' ggf. Trace ausgeben #if Empfangsueberwachung_testmodus Print #2 , "Scheduler: Loeschen aller Buffer und Datenstrukturen" #endif ' Timeoutflag zurücksetzen Receive_timeout_flag = False ' ----- RS485 ----- ' Sende- und Empfangsstrukturen initialisieren Rx_bufferindex = 1 ' Index auf 1 Tx_bufferindex = 1 ' Index auf 1 Rs485_broadcastflag = False ' Adresstyp zurücksetzen ' Eingangsbuffer und Ausgangsbuffer löschen Clear Serialin Clear Serialout End If ' Timer abgelaufen End If ' Timeourüberwachung aktiv Return '-- End Scheduler ------------------------------------------------------------- '------------------------------------------------------------------------------ ' Devices schließend und ggf. "Terminate Programm execution" '------------------------------------------------------------------------------ Close #3 ' RS232 Kanal 3 schließen Close #2 ' RS232 Kanal 2 schließen Close #1 ' RS232 Kanal 1 schließen ' System halt End 'end program '------------------------------------------------------------------------------ ' Definition von globalen Konstantenfeldern '------------------------------------------------------------------------------ Igbt_schalttabelle: Data 255 , 234 , 224 , 216 , 210 , 204 , 198 , 193 Data 189 , 185 , 179 , 175 , 171 , 167 , 163 , 159 Data 155 , 151 , 148 , 144 , 140 , 136 , 130 , 126 Data 120 , 116 , 110 , 105 , 99 , 91 , 81 , 60 ' ---------------------------------------------------------------------------- '###################################### END ################################### '################################### Historie ################################# ' 01.08.2010 : Version 0.0 ' Beginn der Implementierungen für StarLight ' 14.02.2011 : Version 1.0 ' Erste inbetriebgenommene Gesamtversion '##############################################################################