/******************************************* * * Igor-Amperemeter * * (C) Fingers elektrische Welt 2010 * *******************************************/ #include #include #include #include #include #include #include #include "defines.h" #pragma config OSC = HS // >----- Mach mal Pause ---------< #define XTAL_FREQ 4MHZ // Jaja, ich WEISS dass das falsch ist *Grummel* #define MHZ *1000 #define Lampe PORTBbits.RB5 // Lampenpin mit SolidState-Relais #define DelayUs(x) { unsigned int _dcnt; \ _dcnt = (x)/(12MHZ/(XTAL_FREQ))|1; \ while(--_dcnt != 0) \ continue; } // >----- Mach mal Pause ---------< // Diverses char outpbuf [Buflen]; // Ausgabepuffer; volatile unsigned long Timerticks = 0; // Systemticker alle 10ms // Zeitmessung volatile unsigned long SekundenTicker = 0; // Systemticker jede Sekunde ++ volatile unsigned int MinutenTicker = 0; // Jede Minute 1 rauf char Lichtblitzer = FALSE; // Hatter schon geblinkt ? void main (void); void InterruptHandlerHigh (void); /************************** * * Systemticker erhöhen * **************************/ void Systemticker (void) { Timerticks++; //------------------------- // Sekundenweise ausführen //------------------------- if ((Timerticks % 100) == 0) { // Sekundenzähler SekundenTicker++; if (( SekundenTicker % 60) == 0) MinutenTicker++; } // Von if ((Timerticks % 100) == 0) } /************************** * * Systemticker auslesen * **************************/ long Get_Ticker (void) { return (Timerticks); } /************************************* * * Verzögern im Millisekundenbereich * *************************************/ void Delayms (int time) { unsigned long ticker; ticker = Get_Ticker (); while ( (ticker + (time / 10)) > Get_Ticker () ) { ClrWdt(); } } //---------------------------------------------------------------------------- // High priority interrupt vector #pragma code InterruptVectorHigh = 0x08 void InterruptVectorHigh (void) { _asm goto InterruptHandlerHigh //jump to interrupt routine _endasm } //---------------------------------------------------------------------------- // High priority interrupt routine #pragma code #pragma interrupt InterruptHandlerHigh void InterruptHandlerHigh () { //-------------------- // Timer 1 Überlauf ? //-------------------- if (PIR1bits.TMR1IF) { Systemticker (); // Systemticker erhöhen PIR1bits.TMR1IF=0; // Clear Interrupt-Flag // Werte für 10 MHz TMR1L=0xCB; // Timer 1 neu vorladen (0xF3CB = 10ms) TMR1H=0xF3; // n = 2^16 - t [s] * 625000 } // From Timer 1 Überlauf return; // Zurück zum Hauptprogramm } /*************************** * * Wandlerwert reinlutschen * ***************************/ unsigned int ADCGetRaw (void) { //----------------- // Wo solls rein ? //----------------- ADCON0bits.CHS2 = 0; ADCON0bits.CHS1 = 0; ADCON0bits.CHS0 = 0; DelayUs (1000); // Kondensator laden ADCON0bits.GO = 1; // Los gehts while (ADCON0bits.GO); return (ADRES); } /****************************** * * Startklar machen den Eimer * ******************************/ void sysinit (void) { unsigned int Lichtwert = 0; TRISA = 0b00000001; // AN0 = Lichtsensor TRISB = 0b00000010; // RB0 = Relais; RB1 = Taster TRISC = 0b00000000; ClrWdt(); //------------ // Timer-Init //------------ PIE1bits.TMR1IE=1; // enable Interrupt of TMR1 T1CON=49; // Prescaler=1:8 + Timer on (49) INTCONbits.PEIE=1; // Peripherie Int=on INTCONbits.GIE=1; // Define Interupts ClrWdt(); //-------------------------- // AD-Wandler-Einstellungen //-------------------------- ADCON0bits.ADCS1 = 1; ADCON0bits.ADCS0 = 0; ADCON0bits.ADON = 1; // Wandler ein ADCON1bits.ADFM = 1; // Rechtsseitig ADCON1bits.PCFG3 = 0; // Externe Referenz, alle Kanäle Analog ADCON1bits.PCFG2 = 0; ADCON1bits.PCFG1 = 0; ADCON1bits.PCFG0 = 0; //------------------- // PWM-Einstellungen //------------------- // Ausgang startklar machen TRISC &= ~0b00000000; // PWM Duty Cycle bit1 and bit0 CCP1CONbits.DC1B1 = 0; CCP1CONbits.DC1B0 = 0; // PWM-Modus CCP1CONbits.CCP1M3 = 1; CCP1CONbits.CCP1M2 = 1; CCP1CONbits.CCP1M1 = 0; CCP1CONbits.CCP1M0 = 0; // Startwert für PWM setzen CCPR1L = 20; // Timer 2 klarmachen PR2 = 0xFF; // Postscaler 1:16 T2CONbits.TOUTPS3 = 1; T2CONbits.TOUTPS2 = 1; T2CONbits.TOUTPS1 = 1; T2CONbits.TOUTPS0 = 1; // Prescaler 1:16 T2CONbits.T2CKPS1 = 1; T2CONbits.T2CKPS0 = 1; // Und los T2CONbits.TMR2ON = 1; // Zufallsgenerator starten Lichtwert = ADCGetRaw (); srand (Lichtwert); Lampe = 1; Delayms (100); Lampe = 0; Delayms (100); Lampe = 1; Delayms (100); Lampe = 0; Delayms (100); Lampe = 1; Delayms (100); Lampe = 0; Delayms (100); } /*************************************** * * Hier geht das total los das Mopped ! * ***************************************/ void main() { unsigned int Zufallswert; unsigned int Zufallstrom; char Rauf; signed char Zuckwert; unsigned int Zeitschleife; sysinit (); // Mach das hier mal, bis du kotzen musst while (1) { ClrWdt(); // Die nächsten Zufallswerte generieren Zufallswert = rand (); Zufallswert /= 6550; Zufallswert += 3; // Zufallswert = 3 + (rand () / 6550); // Erzeugt bei RAND_MAX = 2^15 einen Wert zwischen 3 und 8 für die Zeitschleife // Zufallstrom = 30 + (rand () / 819); // Erzeugt bei RAND_MAX = 2^15 einen Wert zwischen 30 und 70 für den Mittelwert der PWM Zufallstrom = rand (); Zufallstrom /= 160; Zufallstrom += 30; // Die folgende Schleife läuft also 3-8 Sekunden Rauf = 1; Zuckwert = 0; Zeitschleife = SekundenTicker; while (SekundenTicker <= (Zeitschleife + Zufallswert)) { // Zeitschleife = SekundenTicker; // Zeit messen ClrWdt(); CCPR1L = (char)(Zufallstrom + Zuckwert); // PWM setzen // Jetzt einfach ein wenig mit dem Zeiger zucken // Kurze Pause, dann PWM-Wert ändern Delayms (200); if (Rauf) Zuckwert++; else Zuckwert--; if (Zuckwert == 20) Rauf = 0; if (Zuckwert == -20) Rauf = 1; } // Von while (Zeitschleife <= (Zeitschleife + Zufallswert)) // Mit Lampe rumblinken if ((MinutenTicker % 5) == 0) { if (!Lichtblitzer) { Lichtblitzer = TRUE; Lampe = 1; Delayms (100); Lampe = 0; } } else Lichtblitzer = FALSE; } // Von While (1) } // Thats all folks