'(
**************************************************************
* Dieters SmartHome: Alarmanlage *
* V 1.1 (C) Juni 2021 by DiLi-Soft, www.liebl-net.de *
* (compiliert unter BASCOM 2.0.8.3 von 2020) *
* *
* Dieses Programm ist urheberrechtlich geschützt und darf *
* ausschließlich für nichtkommerzielle Zwecke verwendet *
* werden. *
* *
* Gewerbliche Nutzung ist ausgeschlossen!! *
* *
* Weitergabe des Quelltextes ist erwünscht - aber nur *
* komplett, unverändert und mit diesen Copyright-Anmerkungen *
* *
**************************************************************
* *
* Externer Quarz von 3,6864 Mhz für den ATMega664 *
* (oder 164 oder 324) *
* Compare1A-Interrupt: 3686400 / 64 / 5760 = 10Hz = 100ms *
* *
**************************************************************
* *
* Ausstattung: *
* 8 Fensterkontakte (Reed), 8 Motorjalousien, *
* 2 Bewegungssensoren, 1 Schlüsselschalter mit *
* 3 Schaltstellungen: 1 - 0 - 1 , Bedeutung: *
* nur 1 Beweg.-Melder aktiv - AUS - komplett EIN *
* Besonderheit: Bewegungsmelder 1 befindet sich IM Raum *
* von Reed 3, Bewegungsmelder 2 befindet sich NEBEN dem *
* Schlüsselschalter gegenüber der Eingangstür (!). *
* Zum Schlüsselschalter gehören 2 LEDs: *
* Grün und Rot (Bereitschaft - Alarm) *
* *
* Mögliche Blinkfolgen: *
* 1. langsam grün blinkend (Vorbereitungszeit, direkt nach *
* dem Einschalten) *
* *
* 2. 1 - 8 mal kurz rot blinkend, ewig wiederholend (Reed- *
* Kontakt X ist geöffnet -> Warnung dass Fenster auf!) *
* *
* 3. Dauer-Grün (Schalterstellung "Alle", Anlage SCHARF!) *
* *
* 4. Dauer-Rot (ALARM! Sirene ertönt 3 Minuten, Jalousie X *
* fährt herunter, wenn Reed-X-ALARM) *
* *
* 5. Dauer-Rot mit Unterbrechung (wie 4. , Wiederholung) *
* *
* 6. schnell rot blinkend (Beweg.-Melder Flur meldet, 15 *
* Sekunden Zeit zum Abschalten, sonst ALARM *
* *
* 7. rot-grün langsam im Wechsel blinkend (bei Schalter- *
* stellung "WoZi", Überwachung ausschließlich mit *
* Beweg.-Sensor im Wohnzimmer - "Lüftungskontrolle") *
* *
* 8. alle LEDs aus (Anlage ausgeschaltet) *
* *
* Nach einem Stromausfall aktiviert sich die Anlage bei *
* Wiederkehr des Stromes automatisch, überspringt dabei *
* aber die Fenster-Auf-Prüfung ! *
* War vorher ein Fenster-Alarm aktiv, wird das betroffene *
* Fenster gegen Wiederhochfahren auf Dauer geschützt ! *
* *
**************************************************************
')
' ***** PROGRAMMER-Option: "Upload Code and Data" aktivieren - wg. EEPROM-Vorbesetzung *****
'$PROG &HFF,&HFF,&HD1,&HFF ' = Lockbit + Fusebits für !! Mega644 !!
' damit sind JTAG (!) und DIV8 deaktiviert
' ext. Quarz aktiviert und EEPROM vor dem Löschen geschützt
$regfile = "m644def.dat" ' für ATMEGA644 / für ATMEGA164 auf "m164def.dat" setzen
$crystal = 3686400
$baud = 38400 ' später für "TOKEN-RING"
$hwstack = 10
$swstack = 10
$framesize = 40 ' geringe Anforderungen an den Stack
' PINs konfigurieren und Ausgänge voreinstellen:
' Bits: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ddra = 255 ' | Jal. SchlZi | Jal. Balkon | Jal. Kueche | Jal. WC | Jal. WoZi | Jal. Terr | Jal. FeZi | Jal. EsZi | (Ausgänge f. Jalousien-abwärts)
PORTA = 0 ' alles ausschalten
DDRC = 0 ' | Reed SchlZi | Reed Balkon | Reed Kueche | Reed WC | Reed WoZi | Reed Terr | Reed FeZi | Reed EsZi | (Eingänge von Reed)
' Bits: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ddrb = &B10011011 ' | eeLED | frei | frei | Netzakt. | Sirene |(INT2)| LED Grün | LED Rot |
' nicht! nicht!
Portb= &B00000011 ' ausschalten
' Bits: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
DDRD = &B00000010 ' | Schl.-Schalter Alle | Schl.-Schalter WoZi | Beweg-Sens Flur | Beweg-Sens WoZi |(INT1)|(INT0)|(TxD)|(RxD)|
' Port-Aliase:
jalAlle alias porta
reedAlle alias PINC
LedRotNot alias portb.0
LedGrnNot alias Portb.1
Sirene alias Portb.3
Netzakt alias portb.4
eeLED alias portb.7
BewSensorWoZi alias pind.4
BewSensorFlur alias pind.5
SchalterWoZi alias pind.6
SchalterAlle alias pind.7
' TIMER1 konfigurieren:
TCCR1B.CS10=1
TCCR1B.CS11=1 ' Prescaler = 64 für Timer 1
tccr1b.wgm12=1 ' CTC einschalten für Timer 1A
compare1a=5760 ' für Interr. nach 100ms
TIMSK1.OCIE1A=1 ' OnCompare-Interrupt einschalten
' PCINT2 konfigurieren (Reed 1-8) :
pcmsk2 = &B11111111 ' alle relevant (Pins PC0-7)
pcicr.pcie2=1 ' PCINT2 einschalten
' PCINT3 konfigurieren (Schalter "Alle" - Schalter "WoZi" - BewSensor Flur - BewSensor "Wozi" - 0 - 0 - 0 - 0) :
pcmsk3 = &B11110000 ' nur Pins PD4-7
pcicr.pcie3=1 ' PCINT3 einschalten
' Interrupt-Serviceroutinen setzen:
on OC1A onOC1A ' TIMER-Int. alle 100ms; daraus leiten sich die 4 Zeitmesser ab
on PCINT2 onPCINT2 ' Pins PC0-7 -> PCInt16-23 = Reed-Kontakte 1-8
on PCINT3 onPCINT3 ' Pins PD4-7 -> PCInt28-31 = BewSensor "WoZi" + "Alle", Schalter "WoZi" + "Alle"
' LED-Blinkfolgen:
const blinkOff = 0 ' Blinken Rot/Grün ausschalten !!!
const blinkRotFast = 1
const blinkRotInterrupt = 2
const blinkRotXmal = 3
const blinkAlternate = 4
const blinkGrnSlow = 5
' Timer_Presets: zum Testen:
const 15Sek = 150 ' 50 1/10 Seks
const 1Min = 450 ' 50
const 3Min = 1800 ' 100
' Timer-Vars:
dim 15SekTimer as byte ' schnelles Blinken: Beweg.-Melder Flur bis Ausschalten
dim 1MinTimer as word ' Vorbereitungszeit bis scharf
dim 3MinTimer as word ' max. Sirenenlaufzeit
' diverse Vars:
$eeprom
data 0 ' mit Null vorbesetzt:
$data ' landet in der .eep-Datei für den Brenner
dim eeJalAlle as eram byte ' bei Reed-Alarm die betr. Jalousie(n) merken
' nach Stromausfall werden Letztere unten gehalten !!!
dim status as byte
status=0 ' alles auf Anfang!
dim bitTest, jalTest as byte
dim old_reedAlle as byte
old_reedAlle=reedAlle ' zum Erkennen von Reed-Veränderungen
dim bewSensorSumme, old_bewSensorSumme as byte
old_bewSensorSumme=bewSensorFlur + bewSensorWoZi ' zum Erkennen von Beweg.-Sensor-Änderungen
dim schalterSumme, old_schalterSumme as byte
old_schalterSumme=schalterAlle + schalterWoZi ' zum Erkennen von Schlüsselschalteränderungen
' Subs():
declare sub jalAbwaerts()
declare sub setBlink(byval blinkMode as byte, byval xMal as byte)
' --------------------- main() -----------------------
SREG.7 =1 ' alle Interrupts freigeben
' ----------------------------------------- Hauptschleife: ------------------------------------------
' Einstiege:
' ------------
do
select case status
case 0: ' alles auf RESET *** 0 ***
15SekTimer=0 ' alle Timer resetten
1MinTimer=0
3MinTimer=0
call setBlink(blinkOff,0) ' evtl. Blinken aus
ledRotNot=1 ' LEDs aus
ledGrnNot=1
Sirene=0 ' Sirene aus
Netzakt=0 ' Netzaktivierung aus
jalAlle=0 ' alle Jalousien-Ausgänge aus
eeLED=0 ' EEPROM-Inhalt-LED aus
status=1
jalTest=eeJalAlle ' ggf. gemerkte offene Reed-Kontakte nach Alarm
if jalTest>0 then
if schalterAlle=1 then ' Schalter auf "Alle"
jalAlle=jalTest ' gemerkte Fenster (dauerhaft !!) auf abwärts setzen
eeLED=1
else
jalTest=0
eeJalAlle=jalTest ' löschen
end if
end if
if schalterAlle=1 then ' nach Stromausfall autom. aktivieren
status=4 ' Reed-Prüfung (Fenster auf) überspringen
end if
if schalterWoZi=1 then ' nach Stromausfall autom. aktivieren
status=31 ' nur WoZi Beweg.-Sensor
end if
case 1: ' warten auf Einschalten
' ----------------------------------------------------------------------
case 2: if reedAlle=0 then ' kein Reed-Kontakt geöffnet *** 1 ***
status=4
else ' Fenster x ist auf !
for bitTest=0 to 7
if reedAlle.bitTest =1 then
incr bitTest ' =x
call setBlink(blinkRotXmal,bitTest) ' x mal blinken
status=3 ' warten auf Godot...
exit for ' nicht weitersuchen
end if
next
end if
case 3: ' STOPP! Warten auf Ausschalten und neu Einschalten !!
' ----------------------------------------------------------------------
' ----------------------------------------------------------------------
case 4: 1MinTimer=1Min
call setBlink(blinkGrnSlow,0)
status=5
case 5: ' auf Ablauf der 1 Minute warten
case 6: call setBlink(blinkOff,0) ' Minute abgelaufen: blinken aus
if jalTest>0 then ' bei Stromausfall und vorherigem Reed-Alarm
ledGrnNot=1
ledRotNot=0 ' Dauer-Rot an
status=11 ' Wiederholungs-SCHARF
else
ledGrnNot=0 ' Dauer-Grün an
status=7 ' SCHARF !!!
end if
case 7: ' warten auf Alarm ...
' ----------------------------------------------------------------------
case 8: 3MinTimer=3Min ' ALARM !!! *** 2 ***
Sirene=1 ' 3 Minuten lang Sirene an
call setBlink(blinkOff,0)
LedRotNot=0 ' rote LED Dauer-ein
LedGrnNot=1 ' grüne LED aus
call jalAbwaerts ' ggf. Jalousie des betroffenen Reeds herunterfahren
status=9
case 9: ' warten auf Ablauf 3 Min-Alarm
case 10: Sirene=0 ' Alarm abgelaufen
status=11
case 11: ' warten auf Wiederholung
' ----------------------------------------------------------------------
case 12: 3MinTimer=3Min ' Wiederholungs-ALARM !!! *** 3 ***
Sirene=1
call setBlink(blinkRotInterrupt,0)
call jalAbwaerts ' ggf. Jalousie herunterfahren !
status=9
' ----------------------------------------------------------------------
case 15: 15SekTimer=15Sek ' Beweg.-Sensor-Flur-ALARM !!! *** 4 ***
call setBlink(blinkRotFast,0) ' schnell rot Blinken
LedGrnNot=1 ' Grün aus
status=16
case 16: ' warten auf Ablauf 15 Sek.
case 17: status=8 ' abgelaufen: weiter wie normal
case 18: 15SekTimer=15Sek ' Wiederholung Flur-Alarm *** 5 ***
call setBlink(blinkRotFast,0) ' schnell rot Blinken
LedGrnNot=1 ' Grün ist aus
status=19
case 19: ' warten Ablauf 15 Sek
case 20: status=12 ' abgelaufen: weiter wie normal Wiederhg.
' ----------------------------------------------------------------------
' ----------------------------------------------------------------------
case 31: 1MinTimer=1Min ' WoZi-Beweg.-Sensor-Alarm aktivieren *** 6 ***
call setBlink(blinkGrnSlow,0) ' langsam grün blinken
status=32
case 32: ' auf Ablauf der 1 Minute warten
case 33: call setBlink(blinkAlternate,0) ' rot - gün im Wechsel blinkend
status=34
case 34: ' warten auf WoZi-Alarm
case 35: 3MinTimer=3Min ' ALARM
Sirene=1 ' 3 Minuten Sirene
call setBlink(blinkOff,0)
LedRotNot=0 ' rote LED Dauer-ein
LedGrnNot=1 ' grüne LED aus
status=36
case 36: ' warten auf Ablauf 3 Min-Alarm
case 37: Sirene=0 ' Alarm abgelaufen
status=33
end select
loop
end ' main()
sub jalAbwaerts() ' testet Reed-Kontakte und fährt ggf. zugehörige Jalousie herunter
if reedAlle=0 then ' kein Reed-Alarm -> keine Aktion nötig !
return
end if
for bitTest=0 to 7
if reedAlle.bitTest =1 then ' offenen Reed-Kontakt x gefunden
' ansonsten:
Netzakt =1 ' Netzaktivierungs-Impuls
waitms 200
Netzakt =0
jalAlle.bitTest=1 ' 200ms später Jalousie x abwärts fahren
end if
next ' wiederholen, so werden auch 2. und weitere Reed-Alarme berücksichtigt!
if jalAlle >0 then
eeJalAlle=jalAlle ' bei Alarm die betroffene(n) durch Alarm heruntergefahrene(n) Jalousie(n) im EEPROM merken
end if
end sub
' "private" Vars fürs Blinken:
dim blinkType, blinkXMal as byte
dim blinkCount, blinkLength as byte : blinkCount=0: blinkLength=0
dim modtemp as byte
sub setBlink(byval blinkMode as byte, byval xMal as byte)
blinkType=blinkMode
if blinkType=blinkOff then
blinkLength=0 ' sauber für neuen Start
end if
if blinkType=blinkRotXmal then
blinkXMal=xMal
blinkCount=xMal
shift blinkCount, LEFT, 2 ' *4 wg. |~~|__ = 400 ms
end if
end sub
' ----------------------------- ISR (Interrupt-Service-Routinen: -----------------------------------
' ----------------------------- TIMER1A: -----------------------------------
onOC1A:
' ------------------ Blinken (rote und grüne LEDs): ---------------------
if blinkType=blinkRotFast then
incr blinkLength
if blinkLength>0 then ' schnelles Blinken Rot
blinkLength=0
LedRotNot=not LedRotNot
end if
end if
if blinkType=blinkRotInterrupt then
incr blinkLength
if blinkLength>14 then
blinkLength=0
LedRotNot=1 ' Dauer-Rot, nur kurz (1/15-tel) unterbrochen
else
LedRotNot=0 ' einschalten
end if
end if
if blinkType=blinkRotXmal then
if blinkLength <10 then ' Vorlauf 0...9: aus
LedRotNot=1
incr blinkLength
end if
if blinkLength =10 then ' Mittelteil: blinkXMal blinken
decr blinkCount
modtemp= blinkCount mod 2
if modtemp=0 then ' nur jedes zweite mal, dann aber doppelt so lange!
LedRotNot= not LedRotNot
end if
if blinkCount =0 then
blinkCount=blinkXMal
shift blinkCount, LEFT, 2 ' *4 wg. |~~|__ = 400 ms
blinkLength=11
end if
end if
if blinkLength >10 then ' Nachlauf 11...20: aus
LedRotNot=1
incr blinkLength
end if
if blinkLength >20 then ' und von Vorne again
blinkLength=0
end if
end if
if blinkType=blinkAlternate then
incr blinkLength
if blinkLength>4 then ' langsam im Wechsel blinken
blinkLength=0
LedGrnNot=not LedGrnNot
LedRotNot= not LedGrnNot
end if
end if
if blinkType=blinkGrnSlow then
incr blinkLength
if blinkLength>4 then ' nur Grün langsam blinken
blinkLength=0
LedGrnNot=not LedGrnNot
end if
end if
' ------------------ 15 Sek-TIMER (Alarm-Verzög. für Beweg.-Sensor Flur): ----------------
if 15SekTimer >0 then
decr 15SekTimer
if 15SekTimer=0 then ' abgelaufen!
if status=16 then ' wenn Beweg.-Sensor-Flur-Alarm
status=17
end if
if status=19 then ' wenn Beweg.-Sensor-Flur-Alarm-Wiederholung
status=20
end if
end if
end if
' ------------------- 1 Min-TIMER (Vorbereitungszeit bis SCHARF): ------------------------
if 1MinTimer >0 then
decr 1MinTimer
if 1MinTimer=0 then ' abgelaufen!
if status=5 then ' von "1 Min warten" nach "1 Min abgelaufen"
status=6
end if
if status=32 then
status=33
end if
end if
end if
' ------------------- 3 Min-TIMER (Dauer Sirenen-Alarm): ---------------------------------
if 3MinTimer >0 then
decr 3MinTimer
if 3MinTimer=0 then ' abgelaufen!
if status=9 then ' normaler Alarm
status=10 ' Sirene aus!
end if
if status=36 then ' nur WoZi-Alarm
status=37 ' Sirene aus!
end if
end if
end if
return
' ---------------------------- Reed-Kontakte (PC0-7): ---------------------------
onPCINT2:
if reedAlle>old_reedAlle then ' es kam etwas hinzu -> steigende Flanke!
old_reedAlle=reedAlle ' letzte Änderung merken
' irgend eine Reed-Schleife wurde geöffnet
if status=7 then
status=8 ' ALARM !!! *** 2 ***
end if
if status=9 then ' Wiederholung, während der vorige Alarm noch läuft
status=12
end if
if status=11 then
status=12 ' Wiederholungs-Alarm nach Ablauf der Sirenenzeit *** 3 ***
end if
else
old_reedAlle=reedAlle ' kleiner -> fallende Flanke: Alarm-Wegfall ignorieren
end if
PCIFR.PCIF2=1 ' evtl. aufgelaufende INTs (Preller) löschen
return
' ---------------- Beweg.-Sensoren und Schlüsselschalter(PD4-7): ----------------
onPCINT3:
' ---------------- Beweg.-Sensoren: ----------------
bewSensorSumme=bewSensorFlur + bewSensorWoZi
if bewSensorSumme>old_bewSensorSumme then ' es kam etwas hinzu -> steigende Flanke
old_bewSensorSumme=bewSensorSumme ' letzte Änderung merken
if bewSensorFlur=1 then ' Beweg.-Sensor Flur hat gemeldet
if status=7 then
status=15 ' ALARM mit Verzögerung !!! *** 4 ***
end if
if status=11 then
status=18 ' Wiederholungs-Alarm mit Verzögerung !!! *** 5 ***
end if
end if
if bewSensorWoZi=1 then ' Beweg-Sensor WoZi hat gemeldet
if status=7 then
status=8 ' ALARM !!!
end if
if status=11 then
status=12 ' Wiederholungs-Alarm
end if
if status=34 then
status=35 ' nur WoZi-Alarm !!!
end if
end if
else ' fallende Flanke ignorieren
old_bewSensorSumme=bewSensorSumme
end if
' --------------Schlüsselschalter: -----------------
schalterSumme=schalterAlle + schalterWoZi
if schalterSumme <> old_SchalterSumme then
old_schalterSumme=schalterSumme' letzte Änderung merken
if schalterSumme>0 then
' ------------------ einschalten: ------------------
if schalterAlle=1 then ' "Alle" eingeschaltet
status=2 ' Start mit Test: Fenster auf? *** 1 ***
end if
if schalterWoZi=1 then ' "WoZi" eingeschaltet
status=31 ' nur "WoZi" scharf *** 6 ***
end if
else
' ------------------ ausschalten: ------------------
status=0 ' ausgeschaltet: alles aus und warten auf Einschalten *** 0 ***
end if
end if
PCIFR.PCIF3=1 ' evtl. aufgelaufende INTs (Preller) löschen
return