1 | //#define F_CPU 8000000 //CPU festlegen
|
2 |
|
3 | //#include <stdio.h> //für die sprintf-Funktion notwendig
|
4 | #include <stdbool.h> //für Bool-Variablen
|
5 | #include <util/delay.h> //für Warteschleifen
|
6 | #include <stdlib.h> //für Zufallszahlen
|
7 | #include <avr/eeprom.h> //für den Speicher
|
8 | #include <avr/interrupt.h> //für Interrupts
|
9 | #include <avr/sleep.h> //für den Schlafmodus
|
10 | #include "uart.h"
|
11 | #include "ports.h"
|
12 | #include "rfm12.h"
|
13 |
|
14 | //Konstanten für Sendekommandos
|
15 | //#define KOMMANDO_PRE "HAAv2" //Prefix zum Sendekommando
|
16 | //#define REED01_ON "R01C01" //Reedkontakt 1 einschalten
|
17 | //#define REED01_OFF "R01C00" //Reedkontakt 1 ausschalten
|
18 | //#define REED01_STATUS "R01S00" //Reedkontakt 1 allg. Status
|
19 | //#define KOMMANDO_SUF "FV1" //Sufix zum Sendekommando (Fuhsy Verschlüsselung v1)
|
20 |
|
21 | //#define CODE "MNiPFuiba140582g" //Verschlüsselungscode
|
22 | #define COMMANDO "012345678901234#"
|
23 |
|
24 | //TODO: Konstanten in Funktion verwenden
|
25 | //Konstanten
|
26 | //#define T_VORALARM = 10000; //Totzeit bis Voralarm zum Alarm wird in ms
|
27 | //#define T_SCHARF = 10000 //Totzeit bis Analge scharf geschaltet wird in ms
|
28 |
|
29 | //Globale Variablen: Zustände der Anlage
|
30 | bool _kontakt_alarm = false;
|
31 | bool _rfm_alarm = false;
|
32 | bool _voralarm = false;
|
33 | bool _alarm = false;
|
34 | bool _anlage_start = false;
|
35 | bool _anlage_scharf = false;
|
36 |
|
37 | //Globale Variablen: Zeitmessungen
|
38 | int16_t _zeit_LED_rot = 0;
|
39 | int16_t _zeit_ms = 0;
|
40 | bool _zeit_LED_rot_reset = false;
|
41 | int16_t _zeit_LED_gruen = 0;
|
42 | bool _zeit_LED_gruen_reset = false;
|
43 | int16_t _zeit_anlage_scharf = 0;
|
44 | bool _zeit_anlage_scharf_reset = false;
|
45 | int16_t _zeit_voralarm = 0;
|
46 | bool _zeit_voralarm_reset = false;
|
47 |
|
48 | void initPorts() //Ports deklarieren
|
49 | {
|
50 | //PB
|
51 | //Output
|
52 | DDRB |= (1<<REL_K1); //Relais K1 OUTPUT
|
53 | DDRB |= (1<<RFM_SEL); //SEL_OUTPUT
|
54 | DDRB |= (1<<RFM_SDI); //SDI_OUTPUT
|
55 | DDRB |= (1<<RFM_SCK); //SCK_OUTPUT
|
56 | //Input
|
57 | DDRB &=~(1<<RFM_SDO); //SDO_INPUT
|
58 |
|
59 | //PC
|
60 | //Output
|
61 | DDRC |= (1<<CS_EXIT); //Externer Zugriff auf Codeschloss
|
62 | //Input
|
63 | DDRC &=~(1<<REED_0); //Reed 0
|
64 | DDRC &=~(1<<REED_1); //Reed 1
|
65 | DDRC &=~(1<<REED_2); //Reed 2
|
66 | DDRC &=~(1<<REED_3); //Reed 3
|
67 | DDRC &=~(1<<CS_REL2); //Relais 2 des Codeschlosses
|
68 |
|
69 | //PD
|
70 | //Output
|
71 | DDRD |= (1<<RFM_POWER); //Ausgang für Spannungsversorgung des RFMs
|
72 | DDRD |= (1<<LED_ROT); //LED für allg. Statuszustand
|
73 | DDRD |= (1<<LED_GRUEN); //LED für "Anlage nicht scharf"
|
74 | DDRD |= (1<<LED_RES); //Reserve
|
75 | //Input
|
76 | DDRD &=~(1<<RFM_IRQ); //IRQ_IN
|
77 | DDRD &=~(1<<CS_REL1); //Relais 1 vom Codeschloss
|
78 |
|
79 | //interne Pull-Up-Widerstände einschalten
|
80 | PORTC |= (1<<CS_REL2); //Realis 2 vom Codeschloss
|
81 | PORTD |= (1<<CS_REL1); //Realis 1 vom Codeschloss
|
82 |
|
83 | //Ports initiaisieren, aus LOW setzten
|
84 | REL_K1_OFF();
|
85 | CS_EXIT_OFF();
|
86 | RFM_OFF();
|
87 | LED_ROT_OFF();
|
88 | LED_GRUEN_OFF();
|
89 | LED_RES_OFF();
|
90 | }
|
91 |
|
92 | void Zustand_Anlage() //allg. Zustand der Alarmanlage abfragen
|
93 | {
|
94 | int16_t zeit = 5000; //Totzeit bis Anlage scharf geschaltet wird in ms TODO: Zeit für Testzwecke runtergesetzt
|
95 |
|
96 | //Relais 1 vom Codeschloss aktiv
|
97 | if (CS_REL1_OPEN())
|
98 | {
|
99 | _anlage_start = true;
|
100 |
|
101 | //Totzeit ist noch nicht abgelaufen.
|
102 | if (_zeit_anlage_scharf <= zeit)
|
103 | {
|
104 | _anlage_scharf = false;
|
105 | }
|
106 |
|
107 | //Totzeit ist abgelaufen
|
108 | else
|
109 | {
|
110 | _anlage_scharf = true;
|
111 | _zeit_anlage_scharf = zeit;
|
112 | }
|
113 | }
|
114 |
|
115 | //Relais 1 vom Codeschloss nicht aktiv
|
116 | else
|
117 | {
|
118 | _anlage_start = false;
|
119 | _anlage_scharf = false;
|
120 | _zeit_anlage_scharf = 0;
|
121 | }
|
122 |
|
123 | //Ein Reedkontakt ist geöffnet
|
124 | /* if (REED_0_OPEN() | REED_1_OPEN() | REED_2_OPEN() | REED_3_OPEN())
|
125 | {
|
126 | _kontakt_alarm = true;
|
127 | }
|
128 |
|
129 | //Alle Reedkontakte sind geschlossen
|
130 | else
|
131 | {
|
132 | _kontakt_alarm = false;
|
133 | }
|
134 | */
|
135 | }
|
136 |
|
137 | void initTimer()
|
138 | {
|
139 | TCCR0 =(1<<CS01) | (1<<CS00); //Vorteiler 64 setzten
|
140 | TCNT0 = 131; //register Vorladen
|
141 | TIMSK |= (1<<TOIE0); //Timer 0 enable
|
142 | sei(); //alle Interrups einschalten
|
143 | }
|
144 |
|
145 |
|
146 | void RFM_Ueberwachung() //RFM-Reed_kontakte abfragen
|
147 | {
|
148 | /* static bool pruefung_start = true; //damit soll nur einmal pro Zeitheit geprüft werden
|
149 | static int wiederholung = 0; //Anzahl der Prüfungswiederholungen
|
150 | //static int zeit_rfm = 0; //Zeitvergleich für Variable "zeit"
|
151 | int zeit = 100; //Zeit für Prüfungsintervalle
|
152 |
|
153 | //Prüft ob die Anlage scharf ist oder gerade startet
|
154 | if (_anlage_start || _anlage_scharf)
|
155 | {
|
156 | RFM_ON(); //Modul einschalten
|
157 | }
|
158 |
|
159 | else
|
160 | {
|
161 | RFM_OFF(); //Modul auschaltet
|
162 | }
|
163 |
|
164 | //Anlage ist scharf geschaltet
|
165 | if (_anlage_scharf)
|
166 | {
|
167 | }
|
168 |
|
169 | //Anlage ist noch nicht scharf
|
170 | else
|
171 | {
|
172 | //Anlage startet gerade
|
173 | if (_anlage_start)
|
174 | {
|
175 | //Wiederholungen für Prüfungsinterval prüfen
|
176 | //Wiederholungen noch nicht erreicht
|
177 | if (wiederholung <= 5)
|
178 | {
|
179 | //Prüfen ob schonmal geprüft wurde
|
180 | if (pruefung_start)
|
181 | {
|
182 | pruefung_start == false; //damit die Prüfung nicht nochmal gestartet wird
|
183 | wiederholung ++; //nur 5mal prüfen
|
184 | //RFM_Kommando(Sender) //RFM als Sender konfiguieren
|
185 | //RFM_Senden(Reed_abfragen);//Reed-Status abfragen
|
186 | //RFM_Kommando(Empfang) //RFM als Empfänger konfiguieren
|
187 | }
|
188 |
|
189 | //noch nicht geprüft
|
190 | else
|
191 | {
|
192 | //Zeit noch nicht erreicht
|
193 | if (zeit_rfm <= zeit -1)
|
194 | {
|
195 | zeit_rfm ++;
|
196 | }
|
197 |
|
198 | //Zeit wurde erreicht
|
199 | else
|
200 | {
|
201 | zeit_rfm == 0;
|
202 | pruefung_start == true;
|
203 | }
|
204 | }
|
205 | }
|
206 |
|
207 | //Wiederholungen erreicht
|
208 | else
|
209 | {
|
210 | _rfm_alarm == true; //RFM-Alarm setzten
|
211 | }
|
212 | }
|
213 |
|
214 | //Anlage startet nicht mehr
|
215 | else
|
216 | {
|
217 | pruefung_start == true; //Prüfungintervall wieder zulassen
|
218 | wiederholung == 0; //Widerholungsinterval zurücksetzten
|
219 | zeit_rfm == 0; //Zeit zurücksetzten
|
220 | }
|
221 | }*/
|
222 | }
|
223 |
|
224 | void Voralarm() //Abfragen ob ein Voralarm vorhanden ist
|
225 | {
|
226 | //Alarmanlage ist scharf gestellt
|
227 | if (_anlage_scharf)
|
228 | {
|
229 | //Reed 0 ist ausgelöst
|
230 | if (REED_0_OPEN())
|
231 | {
|
232 | _voralarm = true;
|
233 | }
|
234 | }
|
235 |
|
236 | //Alarmanlage noch nicht scharf gestellt
|
237 | else
|
238 | {
|
239 | _voralarm = false;
|
240 | }
|
241 | }
|
242 |
|
243 | void Alarm() //Abfragen ob ein Alarm vorhanden ist
|
244 | {
|
245 | int16_t zeit = 10000; //Totzeit bis Voralarm zum Alarm wird
|
246 |
|
247 | //Alarmanlage ist scharf geschaltet
|
248 | if (_anlage_scharf)
|
249 | {
|
250 | //Reed 1, 2 oder 3 ist ausgelöst (Reed 0 ist die Tür)
|
251 | if (REED_1_OPEN() | REED_2_OPEN() | REED_3_OPEN())
|
252 | {
|
253 | REL_K1_ON();
|
254 | _alarm = true;
|
255 | }
|
256 |
|
257 | //Voralarm wurde ausgelöst
|
258 | if (_voralarm)
|
259 | {
|
260 | //Totzeit für Voralarm noch nicht abgelaufen
|
261 | if (_zeit_voralarm < zeit)
|
262 | {
|
263 | }
|
264 |
|
265 | //Totzeit für Voralarm abgelaufen
|
266 | else
|
267 | {
|
268 | REL_K1_ON();
|
269 | _zeit_voralarm = zeit;
|
270 | _alarm = true;
|
271 | }
|
272 | }
|
273 |
|
274 | //Voralarm noch nicht ausgelöst
|
275 | else
|
276 | {
|
277 | _zeit_voralarm = 0;
|
278 | }
|
279 | }
|
280 |
|
281 | //Alarmanlage noch nicht scharf gestellt
|
282 | else
|
283 | {
|
284 | REL_K1_OFF();
|
285 | _alarm = false;
|
286 | _zeit_voralarm = 0;
|
287 | }
|
288 | }
|
289 |
|
290 | void LED_GN() //LED grün für "Alles OK" setzten
|
291 | {
|
292 | static int16_t t_an = 0; //Zeitvariable für LED-Blinkfunktion
|
293 | static int16_t t_aus = 0;
|
294 |
|
295 | //Ein Kontakt ist geöffnet
|
296 | if (_kontakt_alarm)
|
297 | {
|
298 | t_an = 500; //Zeitvariable für LED-Blinkfunktion
|
299 | t_aus = 500; //Zeitvariable für LED-Blinkfunktion
|
300 | }
|
301 |
|
302 | //alle Kontakte geschlossen
|
303 | else
|
304 | {
|
305 | t_an = 0; //Zeitvariable für Dauerlicht
|
306 | t_aus = 0; //Zeitvariable für Dauerlicht
|
307 | }
|
308 |
|
309 | //Anlage ist scharf
|
310 | if (_anlage_scharf)
|
311 | {
|
312 | LED_GRUEN_OFF();
|
313 | _zeit_LED_gruen = 0;
|
314 | }
|
315 |
|
316 | //Anlage ist nicht scharf
|
317 | else
|
318 | {
|
319 |
|
320 | //Blinkfrequenz LED an
|
321 | if (_zeit_LED_gruen <= t_an)
|
322 | {
|
323 | LED_GRUEN_ON();
|
324 | }
|
325 |
|
326 | else
|
327 | {
|
328 | //Blinkfrequenz LED aus
|
329 | if (_zeit_LED_gruen <= t_an + t_aus)
|
330 | {
|
331 | LED_GRUEN_OFF();
|
332 | }
|
333 |
|
334 | //...Zähler wieder zurücksetzten
|
335 | else
|
336 | {
|
337 | _zeit_LED_gruen = 0;
|
338 | }
|
339 | }
|
340 | }
|
341 | }
|
342 |
|
343 | void LED_RT() //LED rot für allg. Betriebszustände setzten
|
344 | {
|
345 | static int16_t t_an = 0; //Zeitvariable für LED-Blinkfunktion
|
346 | static int16_t t_aus = 0;
|
347 |
|
348 | //Wenn einer davon auf true ist, fängt die LED an zu blinken
|
349 | if (_rfm_alarm ||
|
350 | _voralarm || _alarm ||
|
351 | _anlage_start || _anlage_scharf)
|
352 | {
|
353 | //Blinkfrequenz LED an
|
354 | if (_zeit_LED_rot <= t_an)
|
355 |
|
356 | {
|
357 | LED_ROT_ON(); //LED einschalten
|
358 | }
|
359 |
|
360 | //Blinkfrequenz LED aus
|
361 | else
|
362 | {
|
363 | if (_zeit_LED_rot <= t_an + t_aus)
|
364 | {
|
365 | LED_ROT_OFF();
|
366 | }
|
367 |
|
368 | //...Zähler wieder zurücksetzten
|
369 | else
|
370 | {
|
371 | _zeit_LED_rot = 0;
|
372 | }
|
373 | }
|
374 | }
|
375 |
|
376 | //keine Aktivität der Anlage vorhanden
|
377 | else
|
378 | {
|
379 | LED_ROT_OFF();
|
380 | }
|
381 |
|
382 | //Blinkzeiten setzten, Reihenfolge beachten
|
383 | //Anlage startet gerade
|
384 | if (_anlage_start)
|
385 | {
|
386 | t_an = 500; //in Milisekunden
|
387 | t_aus = 500;
|
388 | }
|
389 |
|
390 | //Anlage ist scharf
|
391 | if (_anlage_scharf)
|
392 | {
|
393 | t_an = 100; //in Milisekunden
|
394 | t_aus = 2900;
|
395 | }
|
396 |
|
397 | //Voralarm ist vorhanden
|
398 | if (_voralarm)
|
399 | {
|
400 | t_an = 250; //in Milisekunden
|
401 | t_aus = 250;
|
402 | }
|
403 |
|
404 | //Alarm ist vorhanden
|
405 | if (_alarm)
|
406 | {
|
407 | t_an = 0; //in Milisekunden
|
408 | t_aus = 0;
|
409 | }
|
410 | }
|
411 |
|
412 | void Verschluesseln(char kommando[])
|
413 | {
|
414 | /*
|
415 | int zufall = rand(); //Zufallszahl erzeugen
|
416 | int i = 0; //Laufvariable
|
417 | int ascii[16] = {0}; //Array für Sendetext
|
418 | int ascii_int; //zeigen als integerzahl
|
419 |
|
420 | //Prefix "HAAv2"
|
421 | for(i=0; i<=4; i++)
|
422 | {
|
423 | ascii[i] = zufall + CODE[i] + KOMMANDO_PRE[i];
|
424 | }
|
425 |
|
426 | //Kommando "R01C01"
|
427 | for(i=5; i<=10; i++)
|
428 | {
|
429 | ascii_int = *&kommando[i];
|
430 | ascii[i] = ascii_int;
|
431 | //ascii[i] = zufall + CODE[i] + ascii_int;
|
432 | }
|
433 |
|
434 | //Laufvariable "1"
|
435 | ascii[11] = zufall + CODE[11];
|
436 |
|
437 | //Zufallszahl "#"
|
438 | ascii[12] = zufall + CODE[12];
|
439 |
|
440 | //Sufix "FV1"
|
441 | for(i=13; i<=15; i++)
|
442 | {
|
443 | ascii[i] = zufall + CODE[i] + KOMMANDO_SUF[i];
|
444 | }
|
445 |
|
446 | while(true)
|
447 | {
|
448 | int zufall = rand();
|
449 |
|
450 | int b0 = zufall + 'M' + 72; //H
|
451 | int b1 = zufall + 'N' + 65; //A
|
452 | int b2 = zufall + 'i' + 65; //A
|
453 | int b3 = zufall + 'P' + 118;//v
|
454 | int b4 = zufall + 'F' + 50; //2
|
455 | int b5 = zufall + 'u' + 82; //R
|
456 | int b6 = zufall + 'i' + 48; //0
|
457 | int b7 = zufall + 'b' + 49; //1
|
458 | int b8 = zufall + 'a' + 67; //C
|
459 | int b9 = zufall + '1' + 48; //0
|
460 | int b10 = zufall + '4' + 49;//1
|
461 | int b11 = zufall + '0' + 49;//1
|
462 | int b12 = zufall + '5'; //reine Zufallszahl
|
463 | int b13 = zufall + '8' + 116;//F
|
464 | int b14 = zufall + '5' + 86;//V
|
465 | int b15 = zufall + 'g' + 49;//1
|
466 |
|
467 | int zufall_x = b15 - 'g';
|
468 | int c0 = b0 - zufall_x - 'M';
|
469 | int c1 = b1 - zufall_x - 'N';
|
470 | int c2 = b2 - zufall_x - 'i';
|
471 | int c3 = b3 - zufall_x - 'P';
|
472 | int c4 = b4 - zufall_x - 'F';
|
473 | int c5 = b5 - zufall_x - 'u';
|
474 | int c6 = b6 - zufall_x - 'i';
|
475 | int c7 = b7 - zufall_x - 'b';
|
476 | int c8 = b8 - zufall_x - 'a';
|
477 | int c9 = b9 - zufall_x - '1';
|
478 | int c10 = b10 - zufall_x - '4';
|
479 | int c11 = b11 - zufall_x - '0';
|
480 | int c12 = b12 - zufall_x - '5';
|
481 | int c13 = b13 - zufall_x - '8';
|
482 | int c14 = b14 - zufall_x - '5';
|
483 | int c15 = b15 - zufall_x - 'g';
|
484 | }
|
485 | */
|
486 | }
|
487 |
|
488 | void Test()
|
489 | {
|
490 | static int16_t zeit_anff = 0;
|
491 | static int16_t zeit_ende = 0;
|
492 | static bool erstes_mal = true;
|
493 |
|
494 | int16_t zeit_diff = 0;
|
495 | int16_t t_an = 500;
|
496 | int16_t t_aus = 500;
|
497 | int16_t addition = 0;
|
498 |
|
499 | //damit beim ersten mal die Zeit notiert wird
|
500 | if (erstes_mal)
|
501 | {
|
502 | erstes_mal = false;
|
503 | zeit_anff = _zeit_ms;
|
504 | zeit_ende = _zeit_ms;
|
505 | }
|
506 |
|
507 | //bei nicht ersten mal wird dann nur die Endzeit notiert
|
508 | else
|
509 | {
|
510 | zeit_ende = _zeit_ms;
|
511 | }
|
512 |
|
513 | //damit beim errechnen keine negativen zahlen kommen
|
514 | //da die Zeit bis 999 geht und dann wieder mit 0 anfängt
|
515 | if (zeit_anff > zeit_ende)
|
516 | {
|
517 | addition = 1000;
|
518 | }
|
519 | zeit_diff = (zeit_ende + addition) - zeit_anff;
|
520 |
|
521 | //Zeit zum Ausschalten noch nicht erreicht
|
522 | if (zeit_diff <= t_an)
|
523 | {
|
524 | LED_ROT_ON();
|
525 | }
|
526 |
|
527 | //Zeit zum ausschalten erreicht
|
528 | else
|
529 | {
|
530 | if (zeit_diff <= t_an + t_aus)
|
531 | {
|
532 | LED_ROT_OFF();
|
533 | }
|
534 | else
|
535 | {
|
536 | //alle Zähler wieder reseten
|
537 | erstes_mal = true;
|
538 | zeit_anff = 0;
|
539 | zeit_ende = 0;
|
540 | }
|
541 | }
|
542 |
|
543 |
|
544 | }
|
545 |
|
546 |
|
547 | int main(void)
|
548 | {
|
549 | initPorts(); //Ports deklarieren
|
550 | initUART(); //UART initialisieren
|
551 | initTimer(); //Timer initialisieren
|
552 |
|
553 | RFM_ON(); //Modul einschalten
|
554 | _delay_ms(100); //etwas warten bis das Modul bereit ist
|
555 | init_RFM_Ports(); //RFM-Ports initialisieren
|
556 | init_RFM(); //RFM initialisieren
|
557 |
|
558 | //Hauptschleife
|
559 | while(true)
|
560 | {
|
561 | Test();
|
562 | Zustand_Anlage(); //Anlagenzustand abfragen
|
563 | //RFM_Ueberwachung(); //RFM-Kontakte abfragen
|
564 | DATEN_SENDEN(COMMANDO);
|
565 | //Verschluesseln (&REED01_ON[0]);
|
566 | Voralarm(); //Abfragen ob ein Voralarm vorhanden ist
|
567 | Alarm(); //Abfragen ob ein Alarm vorhanden ist
|
568 | LED_GN(); //Ausgang der grünen LED setzten
|
569 | //LED_RT(); //Ausgang der roten LED setzten
|
570 | //_delay_ms(1000);
|
571 | }
|
572 | }
|
573 |
|
574 | //Time-Interrupt, wird jede ms ausgelöst
|
575 | ISR(TIMER0_OVF_vect)
|
576 | {
|
577 | //TODO: Zeiten müssen zurückgesetzt werden, wenn sie nicht gebraucht werden.
|
578 | //z.b. während der Funktion "Daten senden" die ca. 6ms dauert.
|
579 | //sonst sind die Zeitvariablen > 0 und die LED zeigen was falsches an
|
580 |
|
581 | //Zeitkonstsnten für verschiedene Aufaben
|
582 | //_zeit_LED_rot ++;
|
583 | //_zeit_LED_gruen ++;
|
584 | //_zeit_anlage_scharf ++;
|
585 | //_zeit_voralarm ++;
|
586 |
|
587 | TCNT0 = 131; //Register Nachladen
|
588 | //Zu testzwecken
|
589 | if (_zeit_ms < 999)
|
590 | {
|
591 | _zeit_ms ++;
|
592 |
|
593 | }
|
594 |
|
595 | else
|
596 | {
|
597 | _zeit_ms = 0;
|
598 | }
|
599 | }
|