#include #include "lcd-routines.h" // In dieser Datei werden Einstellungen für das Display vorgenommen !! #include // Include für Delay Funktion // #include // Include für Datentypen // #include // Include für sprintf Befehl #include // Für Interrups nötig #include #include // Include für den Watchdog (Auto-Reset) #define F_CPU 8000000UL // 8 Mhz Quarz void LichtInit(void); // Einmalige Initialisieren der Mittelwertpuffers und Tag/Nacht Variable mit aktuellen ADWERT void Schalter(void); // Prototyp für Funktion ohne Übergabewert void ADWandlung(void); void Display(void); void Laufzeit(void); // Überwachung der Laufzeit void Senden(void); // Sende Kommando via 433MHz Modul an Slave void MAP_INPUTS (void); void MAP_OUTPUTS (void); // VAriablen für 433MHz Sendefunktion char *msgR = "R"; // Sendezeichen 1 char *msgH = "H"; // Sendezeichen 2 // Variablen für ADWert uint8_t i = 0, a = 0, ton = 0; int16_t ADWERT = 0, Mittelwert = 0; uint16_t Mittel_Buffer[21] = {20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20}; //Array initialisieren mit 20 (Nacht) //float AdAufloesung = 0.004883; // 5 Vcc / 1024 = 0.004883 char Buffer[20]; // Feld für ASCII-String Umwandlung, wird mehrmals verwendet uint8_t SwitchStep = 0, UpFlag = 0, DownFlag = 0, Night = 0, RelaisOnDelay = 0; uint16_t counter10mS = 0, counter1S = 0, counter30S = 0, counter90S = 0, Errorcounter = 0, ErrorcounterDisplay = 0, DelayCounter = 0, parameter = 0, Sendecounter = 0; volatile uint8_t flag10ms = 0, flag1s = 0, flag30s = 0, flag90s = 0, N_Flanke = 0, Toggle1s = 0; // In/Out flags uint8_t CamUp, CamDown, ButtonUp, ButtonDown, ButtonStop, SwitchAutoOn, LED, RelaisOn, RelaisTurn; uint16_t Abschaltung = 190; // Laufzeitfehler in Sekunden uint16_t Lichtgrenze = 18; // Grenzwert für Tag/Nacht Erkennung uint8_t TagVerzoegerung = 40; // Verzögerung Rollladen hoch nachdem ADWERT Tag erkennt in 90s (40 = 1h) uint16_t Sendezyklen = 60; // Anzahl von Sendezyklen zum Slave //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ int main(void) { DDRC = 0x08; // Setze Port C Pin3 als Ausgang, der Rest sind Eingänge PORTC |= (1<= 5) // Alle 10ms (2,048ms X 5) { flag10ms = 1; counter10mS = 0; wdt_reset(); // Watchdog zyklisch zurücksetzen sonst Auto Reset } //----1 s---- if(counter1S >= 488) // Alle 1000ms (2,048ms X 488) { flag1s = 1; Toggle1s =! Toggle1s; counter1S = 0; } //----30 s---- if(counter30S >= 14648) // Alle 30s (2,048ms X 14648) { flag30s = 1; counter30S = 0; } //----90 s---- if(counter90S >= 43945) // Alle 90s (2,048ms X 43945) { flag90s = 1; counter90S = 0; } } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ void MAP_INPUTS (void) { // define i/o on port C + D #define iCamUp 5 #define iCamDown 4 #define iButtonUp 3 #define iButtonDown 1 #define iButtonStop 2 #define iSwitchAuto 0 // map inputs CamUp = (PINC &(1<= 20 ) // Delay 200ms { RelaisOn = 1; SwitchStep++; } break; // ---------------------------------------------------------------- // Motor movement up/down case 2: LED = Toggle1s; Errorcounter++; if (( Errorcounter >= ( Abschaltung * 100 )) || (( SwitchAutoOn == 0 ) && ( ButtonStop == 1 ))) { RelaisOn = 0; SwitchStep++; } if ((( DownFlag == 1 ) && ( CamDown == 1 )) || (( UpFlag == 1 ) && ( CamUp == 1 ))) { RelaisOn = 0; SwitchStep++; } break; // ---------------------------------------------------------------- // Check error counter triggered case 3: LED = 1; if ( Errorcounter >= ( Abschaltung * 100 )) { cli(); // Interrups abschalten wdt_disable(); // Watchdog deaktivieren sonst Auto-Reset nach eingestellter Zeit while(1) // Fehlerabschaltung { PORTD |= (1<= 200 ) { LED = 0; SwitchStep = 0; } break; // ---------------------------------------------------------------- // Reset sequences default: RelaisOn = 0; SwitchStep = 0; break; } } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ void ADWandlung(void) { ADWERT = ADCL; // ADC Low Wert in Variable laden ADWERT += (ADCH << 8); // ADC High Wert in Varible laden. High Wert wird 8 Bits nach links geschoben //--------Mittelwertbildung--------- if ( i<=20 ) // Gleitende Mittelwertbildung über 20 Werte { Mittel_Buffer[i] = ADWERT; i++; } else { i=0; } Mittelwert = 0; for( a=0;a<20;a++ ) // for Schleife um 20 Werte zu addieren { Mittelwert = Mittelwert + Mittel_Buffer[a]; } Mittelwert = Mittelwert / 20; if (Mittelwert <= Lichtgrenze) // Grenzwert auf 30min Mittelwert für Tag/Nacht Erkennung { if (ton >= TagVerzoegerung) // Tagverzögerung um 1h 40 X 90s { Night = 0; } else { ton++; } } else { Night = 1; ton = 0; } } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ void Display(void) { lcd_clear(); // Aktuellen AD Wert ausgeben lcd_setcursor( 0, 1 ); lcd_string("Ac."); if (ADWERT < 1000) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 1000 if (ADWERT < 100) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 100 if (ADWERT < 10) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 10 itoa( ADWERT, Buffer, 10 ); // Umwandlung von Zahl in ASCII-String, 10 für Dezimalsystem lcd_string(Buffer); // Ausgabe an Display // Aktuellen AD Mittelwert ausgeben lcd_setcursor( 9, 1 ); lcd_string("Mi."); if (Mittelwert < 1000) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 1000 if (Mittelwert < 100) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 100 if (Mittelwert < 10) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 10 itoa( Mittelwert, Buffer, 10 ); // Umwandlung von Zahl in ASCII-String, 10 für Dezimalsystem lcd_string(Buffer); // Ausgabe an Display // Aktuelle Vezögerung für Tag ausgeben lcd_setcursor( 0, 2 ); lcd_string("ton."); if (ton < 10) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 10 itoa( ton, Buffer, 10 ); // Umwandlung von Zahl in ASCII-String, 10 für Dezimalsystem lcd_string(Buffer); // Ausgabe an Display } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ void Laufzeit(void) { // Aktuellen Errorcounter ausgeben ErrorcounterDisplay = Errorcounter / 100; lcd_setcursor( 7, 2 ); lcd_string("Er."); if (ErrorcounterDisplay < 100) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 100 if (ErrorcounterDisplay < 10) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 10 itoa( Night, Buffer, 10 ); // Umwandlung von Zahl in ASCII-String, 10 für Dezimalsystem lcd_string(Buffer); // Ausgabe an Display // Überwachung Nockenschalter lcd_setcursor( 14, 2 ); if ( CamDown == 0 ) { lcd_string("0"); } else { lcd_string("1"); } lcd_setcursor( 15, 2 ); if ( CamUp == 0 ) { lcd_string("0"); } else { lcd_string("1"); } } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ void Senden(void) { if (( Night == 1 ) && ( N_Flanke == 0 )) // Flankenbildung bei Tag/Nacht Wechsel zum löschen vom Sendecounter - nur 1 Zyklus { N_Flanke = 1; Sendecounter = 0; } if (( Night == 0 ) && ( N_Flanke == 1 )) // Flankenbildung bei Tag/Nacht Wechsel zum löschen vom Sendecounter - nur 1 Zyklus { N_Flanke = 0; Sendecounter = 0; } if ( ButtonStop == 1 ) // Lösche Sendecounter manuell { Sendecounter = 0; } // -------------------------------------Senden--------------------------------------------- if ( Sendecounter <= Sendezyklen ) // Sende Anzahl parametrierter Telegramme { Sendecounter++; if (Night == 1) { vw_send((uint8_t *)msgR, strlen(msgR)); // Sende Rollladen runter Befehl "R" an Slave vw_wait_tx(); // Warte bis fertig } else { vw_send((uint8_t *)msgH, strlen(msgH)); // Sende Rollladen hoch Befehl "H" an Slave vw_wait_tx(); // Warte bis fertig } } } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ void LichtInit(void) { //Einmalige Initialisieren der Mittelwertpuffers und Tag/Nacht Variable mit aktuellen ADWERT _delay_ms(1000); // Warte bis ADC bereit ADWERT = ADCL; // ADC Low Wert in Variable laden ADWERT += (ADCH << 8); // ADC High Wert in Varible laden. High Wert wird 8 Bits nach links geschoben for(a=0;a<20;a++) // for Schleife um 20 Werte in Buffer zu füllen { Mittel_Buffer[a] = ADWERT; } if (ADWERT <= Lichtgrenze) // Überprüfung ob bereits Tag oder Nacht ist für init Variable {Night = 0;} else {Night = 1;} lcd_setcursor( 0, 1 ); lcd_string("Ac."); if (ADWERT < 1000) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 1000 if (ADWERT < 100) {lcd_string(" ");} // Leerzeichen vor Wert wenn PWert kleiner 100 if (ADWERT < 10) {lcd_string(" ");} // Leerzeichen vor Wert wenn Wert kleiner 10 itoa( ADWERT, Buffer, 10 ); // Umwandlung von Zahl in ASCII-String, 10 für Dezimalsystem lcd_string(Buffer); // Ausgabe an Display } /* Bei AVR Studio 6 sprintf Funktion einbinden: Project Properties ? Toolchain ? AVR/GNU C-Linker ? Libraries In Libraries (-WI, -I), libprintf_flt.a und libm.a eintragen. Project Properties ? Toolchain ? AVR/GNU C-Linker ? Miscellaneous In Other Linker Flags -Wl,-u,vfprintf eintragen. */