1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include <stdint.h>
|
4 |
|
5 | // ********** Config **********
|
6 |
|
7 | volatile uint32_t seconds = 68400; // Startzeit bei PowerUp (19:00 Uhr)
|
8 | uint8_t daemmerungSeconds = 10; // Dauer der Daemmerung pro PWM-Stufe
|
9 | uint8_t pwmTicksMax = 50; // Anzahl der moeglichen PWM-Werte
|
10 |
|
11 |
|
12 | uint32_t lichtAn_Kanal_1[2] = {25200,57600}; // Licht-An Zeiten (7 & 16 Uhr)
|
13 | uint32_t lichtAusKanal_1[2] = {46800,79200}; // Licht-Aus Zeiten (13 & 22 Uhr)
|
14 | volatile int8_t pwmDirKanal_1 = 1; // PWM Vector bei Startzeit (1 -> wird heller, -1 -> wird dunkler, 0 bleibt so. Andere Werte sind properitär)
|
15 |
|
16 |
|
17 | // ********** Config Ende **********
|
18 |
|
19 | // http://www.avrfreaks.net/forum/tut-c-newbies-guide-avr-timers?name=PNphpBB2&file=viewtopic&t=50106
|
20 | // https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
|
21 |
|
22 | volatile uint16_t octalMilliseconds = 0;
|
23 | uint8_t pwmTicks = 0;
|
24 |
|
25 | volatile uint8_t pwmCurrentKanal_1 = 1;
|
26 | volatile uint8_t pwmChangeTickKanal_1 = 0;
|
27 |
|
28 |
|
29 | int main(void)
|
30 | {
|
31 | TCCR0A |= (1 << WGM01); // Uhr-Timer auf CTC setzen
|
32 | OCR0A = 0x02; // Zaehlgrenze setzen (2)
|
33 | TIMSK0 |= (1 << OCIE0A); // Set the ISR COMPA vect
|
34 | TCCR0B |= (1 << CS02); // Prescaler auf 256 setzen
|
35 |
|
36 | /**
|
37 | TCCR2A |= (1 << WGM21); // PWM-Timer auf CTC setzen
|
38 | OCR2A = 0x02; // Zaehlgrenze setzen (2)
|
39 | TIMSK2 |= (1 << OCIE2A); // Set the ISR COMPA vect
|
40 | TCCR2B |= (1 << CS21) | (1 << CS21); // Prescaler auf 256 setzen
|
41 | **/
|
42 |
|
43 | sei(); // Interrupts an
|
44 |
|
45 | DDRD = 0b11111100; // Port D auf Output setzen, Pin 0 & 1 bleiben Input (Serial RX und TX)...
|
46 | PORTD = 0b00000000; // und erstmal alle Ausgaenge auf 0.
|
47 |
|
48 | while(1) {
|
49 | // if(octalMilliseconds >= 31250) { // Sollten mit dem Prescaler 256 und der Zaehlgrenze von 2 genau eine Sekunde sein...
|
50 | if(octalMilliseconds >= 20838) { // Das ist wirklich eine Sekunde (ungefaehr...)
|
51 | seconds++;
|
52 | octalMilliseconds = 0;
|
53 | if(seconds >= 86400) { //Reset der Sekunden am Tagesende
|
54 | seconds = 0;
|
55 | }
|
56 | // PWM-Setzen Kanal 1
|
57 | if((seconds == lichtAn_Kanal_1[0]) || (seconds == lichtAn_Kanal_1[1])) {
|
58 | pwmDirKanal_1 = 1;
|
59 | }
|
60 | if((seconds == lichtAusKanal_1[0]) || (seconds == lichtAusKanal_1[1])) {
|
61 | pwmDirKanal_1 = -1;
|
62 | }
|
63 | if(seconds == 75600) { // Extra: Kanal um 21:00 Uhr runterdimmen
|
64 | pwmDirKanal_1 = -2;
|
65 | }
|
66 | if(pwmDirKanal_1 != 0) {
|
67 | if (pwmChangeTickKanal_1 == daemmerungSeconds) {
|
68 | pwmChangeTickKanal_1 = 0;
|
69 | pwmCurrentKanal_1 = pwmCurrentKanal_1 + pwmDirKanal_1;
|
70 | if ((pwmDirKanal_1 == -2) && (pwmCurrentKanal_1 <= 9)) { // Extra: Kanal um 21:00 Uhr runterdimmen
|
71 | pwmDirKanal_1 = 0;
|
72 | }
|
73 | if ((pwmCurrentKanal_1 == pwmTicksMax) || (pwmCurrentKanal_1 == 0)) { // wenn PWM-Max oder 0 erreicht sind, PWM-Dir wieder auf 0 setzen
|
74 | pwmDirKanal_1 = 0;
|
75 | }
|
76 | }
|
77 | pwmChangeTickKanal_1++;
|
78 | }
|
79 | // ###################
|
80 | }
|
81 | }
|
82 | }
|
83 |
|
84 | /**
|
85 | ISR (TIMER0_COMPA_vect) // timer0 Uhr, alle 8 msec
|
86 | {
|
87 | octalMilliseconds++;
|
88 | }
|
89 | **/
|
90 |
|
91 | //ISR (TIMER2_COMPA_vect) { // timer2 PWM, alle 32µsec
|
92 | ISR (TIMER0_COMPA_vect) { // Da keine zwei Timer funktionieren, Umbau auf nur einen Timer fuer alles
|
93 | // PWM-Teil
|
94 | if(pwmTicks <= pwmCurrentKanal_1) {
|
95 | PORTD |= (1 << PD7); // Pin 7 auf 1
|
96 | }
|
97 | else {
|
98 | PORTD &= ~(1 << PD7); // Pin 7 wieder auf 0
|
99 | }
|
100 | // ##############
|
101 |
|
102 | if(pwmTicks >=pwmTicksMax) { // PWM-Zyklus resetten
|
103 | pwmTicks=0;
|
104 | }
|
105 | pwmTicks++;
|
106 | octalMilliseconds++;
|
107 | }
|