/************************************************************************************************************** * * PIC18F452 * * Lötbad * * Autor : Finger * *************************************************************************************************************/ #include #include #include #include #include #include #include #define Buflen 60 #define TRUE 1 #define FALSE 0 // Konstanten und Bit-Deklarationen static bit LCD_RS @ ((unsigned)&PORTB*8+3); // LCD: Register select static bit LCD_EN @ ((unsigned)&PORTB*8+5); // Enable #define LCD_STROBE ((LCD_EN = 1),(LCD_EN = 1),(LCD_EN=0)) // LCD-Zweizeilen-Display #define XTAL_FREQ 4MHZ // Crystal frequency in MHz, in diesem Projekt völliger Quark. Muß erstmal so bleiben ! #define MHZ *1000 // number of kHz in a MHz #define DelayUs(x) { unsigned int _dcnt; \ _dcnt = (x)/(12MHZ/(XTAL_FREQ))|1; \ while(--_dcnt != 0) \ continue; } //---------------------------------------- // IOs - sind ja wahrlich nicht viele.... //---------------------------------------- #define TemperaturCS0 RC0 // CS-Leitung #define TemperaturCS1 RC1 #define TemperaturCS2 RC2 #define TemperaturCS3 RC3 #define TemperaturCLK RC4 // Clock für SPI #define TemperaturSO RC5 // Datenleitung für SPI #define DrehgeberLinks RB0 // Druck-Drehgebereingänge #define DrehgeberRechts RB1 #define DrehgeberPush RB2 #define Heizung RB4 // Schaltausgang für Heizung // Temperatursensoren #define SensorBoden1 0 #define SensorBoden2 1 #define SensorPlatine 2 #define SensorDampf 3 //-------- // Puffer //-------- char outpbuf [Buflen]; //------------- // Allgemeines //------------- volatile unsigned long Timerticks = 0; char NotAusFlag = FALSE; volatile int SekundenTicker = 0; volatile int SekundenTickerCount = 0; //------------------- // Temperaturmessung //------------------- unsigned long SensorRohwort [4]; // Rohdaten aus dem AD-Wandler int Temperatur [4]; // Gemessene Temperaturen #define TemperaturpufferSize 10 int Temperaturpuffer [TemperaturpufferSize][4]; // Ringpuffer int Temperaturpufferzeiger = 0; // Zeiger auf den Ringpuffer volatile int Temperaturticker = 0; // Zeitablauf der Temperaturmessung steuern #define TemperaturtickerMAx 50 volatile char LeseTemperatursensorCount = 0; // Immer schön der Reihe nach, gelle? volatile int TemperaturLeseZaehler = 0; volatile char TemperaturLeseFlag = TRUE; #define TemperaturLeseZaehlerMax 50 //----------- // Bedienung //----------- char StartMenuePos = 0; volatile int KurbelCounter = 0; volatile int KurbelcounterAlt = 0; volatile int KonfigMenuePos = 0; //-------------------- // Temperaturregelung //-------------------- int TemperaturPunkt1 = 80; // Erste Rampe, Zieltemperatur auf Platine int ZeitPunkt1 = 100; // Erste Rampe, Endzeitpunkt int ZeitPlateau = 60; // Haltezeit des Plateaus, Temperaturmessung auf Platine int TemperaturAbbruch = 230; // Endtemperatur ab der der Lötvorgang beendet ist (Über Sensor im Dampf) char Temperreicht = FALSE; // Was läuft gerade? char FlagHauptMenue = FALSE; char FlagKonfigMenue = FALSE; char FlagLoeten = FALSE; volatile int scheissendreck = 0; //------- // UART //------- #define Empfangspuffergroesse 20 char usart_empfangspuffer [Empfangspuffergroesse]; // Puffer für empfangene Zeichen char usart_schreibzeiger = 0; // Zeiger auf den Empfangspuffer (schreiben) char usart_lesezeiger = 0; // Zeiger auf den Empfangspuffer (lesen) char cdummy; // Empfangsregister auslesen char zeiger = 0; // Lasst uns in die Zukunft schauen.... unsigned int Zeilenzaehler = 0; // Wieviele neue Daten haben wir reinbekommen? unsigned int ZeilenzaehlerAlt = 0; //--------------------------------- // Konfiguration des Controllers //--------------------------------- __CONFIG(1, OSCEN & HS); // Quarz 20 Mhz __CONFIG(2, BORDIS & WDTEN); // Watchdog, kein BrownOut __CONFIG(4, LVPDIS & STVREN); // Kein LowVoltageProgramm, Reset bei StackOverflow /*************************************************************************************************************** * * Verzögern im Millisekundebereich * ***************************************************************************************************************/ void DelayMilli (unsigned char cnt) { unsigned char i; do { i = 4; do { DelayUs (2000); } while(--i); } while(--cnt); } /************************************************************************************************************** * * Ein Byte zum LCD schreiben im 4-Bit-Modus. * **************************************************************************************************************/ void lcd_write (unsigned char c) { PORTD = (PORTD & 0xF0) | (c >> 4); DelayUs (100); LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0;DelayUs(10); DelayUs (100); PORTD = (PORTD & 0xF0) | (c & 0x0F); DelayUs (100); LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0; DelayUs(10); DelayUs (100); } /************************************************************************************************************** * * Cursor ein/ausschalten * **************************************************************************************************************/ void lcd_cursor_on (char type) { LCD_RS = 0; // write control bytes if (type) lcd_write (0x0F); else // display on, blink curson on lcd_write (0x0C); // display on, blink curson off DelayMilli (20); } /************************************************************************************************************** * * LCD löschen und Cursor auf Null setzen * **************************************************************************************************************/ void lcd_clear (void) { LCD_RS = 0; lcd_write (0x1); DelayMilli (10); } /************************************************************************************************************** * * String auf LCD ausgeben * **************************************************************************************************************/ void lcd_puts (const char * s) { LCD_RS = 1; // write characters while(*s) lcd_write(*s++); } /************************************************************************************************************** * * Ein Zeichen auf dem Display ausgeben * **************************************************************************************************************/ void lcd_putch (char c) { LCD_RS = 1; // write characters PORTD = (PORTD & 0xF0) | (c >> 4); // oberes Nibble DelayUs(100); LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0; DelayUs(10); DelayUs(100); PORTD = (PORTD & 0xF0) | (c & 0x0F); // unteres Nibble DelayUs (100); LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0; DelayUs(10); DelayUs(100); } /************************************************************************************************************** * * Cursor positionieren * **************************************************************************************************************/ void lcd_goto (unsigned char pos) { LCD_RS = 0; lcd_write (0x80+pos); } /*************************** * * Positioniert den Cursor * (0,0) = Links oben * ***************************/ void lcd_cursorpos (char zeile, char spalte) { switch (zeile) { case 0 : { lcd_goto (spalte); break; } case 1 : { lcd_goto (0x40 + spalte); break; } case 2 : { lcd_goto (0x14 + spalte); break; } case 3 : { lcd_goto (0x54 + spalte); break; } } } /***************************************** * * Text an definierter Position ausgeben * *****************************************/ void lcd_print (char x, char y, const char * s) { lcd_cursorpos (y, x); lcd_puts (s); } /************************************************************************************************************** * * LCD initialisieren * **************************************************************************************************************/ void lcd_init (void) { LCD_RS = 0; // write control bytes DelayMilli (20); // power on delay PORTD = 0x3; // attention! LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0; DelayUs(10); DelayMilli (10); LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0; DelayUs(10); DelayUs (200); LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0; DelayUs(10); DelayMilli (10); PORTD = 0x2; // set 4 bit mode LCD_EN = 1; LCD_EN = 1; DelayUs(10); LCD_EN = 0; DelayUs(10); DelayUs (160); lcd_write (0x28); // 4 bit mode, 1/16 duty, 5x8 font lcd_write (0x08); // display off lcd_write (0x0C); // display on, blink curson off lcd_write (0x06); // entry mode DelayMilli (20); } /***************************************************************************************************************** * * USART-ISR, hängt im Main in der zentralen ISR * *****************************************************************************************************************/ void isr_usart (void) { //---------------------------- // Receive complete-Interrupt //---------------------------- if (RCIF) { // Nächste Schreibposition ermitteln zeiger = usart_schreibzeiger; zeiger++; if (zeiger == Empfangspuffergroesse) zeiger = 0; // Ist das Pufferende erreicht ? Dann Zeichen verwerfen if (zeiger == usart_lesezeiger) cdummy = RCREG; else { usart_empfangspuffer [usart_schreibzeiger] = RCREG; // Zeichen speichern usart_schreibzeiger = zeiger; // Neuen Zeiger setzen } } // From if (RCIF) } /***************************************************************************************************************** * * String nach USART schreiben, nicht ISR-gesteuert * *****************************************************************************************************************/ void print (const char *data) { char xdummy; // Dummyaufnahme des Empfangsregister if (FERR) xdummy = RCREG; if (OERR) { CREN=0; CREN=1; } do { while (!TRMT); // if ( (*data != '\0') && (*data != 0xff) ) TXREG = *data; TXREG = *data; } while ( *++data ); } /***************************************************************************************************************** * * Char nach USART schreiben, nicht ISR-gesteuert * *****************************************************************************************************************/ void put_char_usart (char data) { char xdummy; // Dummyaufnahme des Empfangsregister if (FERR) xdummy = RCREG; if (OERR) { CREN=0; CREN=1; } while (!TRMT); TXREG = data; } /***************************************************************************************************************** * * Zeichen aus USART abholen, liefert 0, falls kein Zeichen vorhanden * *****************************************************************************************************************/ char get_char_usart (void) { char dummy = 0; // Sind überhaupt Zeichen vorhanden ? if (usart_lesezeiger != usart_schreibzeiger) { dummy = usart_empfangspuffer [usart_lesezeiger]; usart_lesezeiger++; if (usart_lesezeiger == Empfangspuffergroesse) usart_lesezeiger = 0; return (dummy); } else return (0); } /***************************************************************************************************************** * * Puffer leeren * *****************************************************************************************************************/ void flush_usart (void) { usart_lesezeiger = usart_schreibzeiger; } /***************************************************************************************************************** * * UART initialisieren * *****************************************************************************************************************/ void UART_Init (void) { // UART-Einstellungen SPBRG=25; TRISC |= 0b10000000; TRISC &= ~0b01000000; TXSTA=0x24; // mit BRGH=1 RCSTA=0x90; // RCIP = 1; // Empfangsinterrupt mit hoher Priorität // RCIE=1; // Receive-Interrupt ein RCIF=0; // Flag=0; } /************************************ * * Stopfe etwas ins interne EEPROM * ************************************/ void EEPromSchreiben( unsigned int ADR, unsigned char DATA) { EEADR = ADR & 0xFF; // Adresse EEDATA = DATA; // Daten EEPGD = 0; // EEProm beschreiben CFGS = 0; WREN = 1; // Schreiben freigeben EECON2 = 0x55; // ist vorgeschrieben muß so gemacht werden damit wird die EECON2 = 0xAA; // Speicherung gestartet WR = 1; // Schreiben while (WR==1); // warten bis fertig, WR wird zurück gesetzt wenn der // Schreibzyklus abgeschlossen ist WREN = 0; // Schreiben sperren } /************************************** * * Puhle etwas aus dem internen EEPROM * **************************************/ unsigned char EEPromLesen(unsigned int ADR) { EEADR = ADR & 0xFF; // Adresse EEPGD = 0; CFGS = 0; RD = 1; return EEDATA; } /****************************************** * * Lutsche ein INT aus dem internen EEPROM * ******************************************/ unsigned int EEPromLesenInt (unsigned int ADR) { int tmp = 0; tmp=EEPromLesen (ADR); tmp+= ((unsigned int) EEPromLesen (ADR+1)) << 8; return (tmp); } /************************************* * * Stopfe ein INT ins interne EEPROM * *************************************/ void EEPromSchreibenINT ( unsigned int ADR, unsigned int DATA) { EEPromSchreiben ( ADR, (char)(DATA & 0x00FF)); EEPromSchreiben ( ADR+1, (char)( (DATA & 0xFF00) >> 8) ); } /************************ * * Systemticker erhöhen * ************************/ void Systemticker (void) { Timerticks++; } /************************ * * Systemticker auslesen * ************************/ unsigned long GetTicker (void) { return (Timerticks); } /************************************* * * Verzögern im Millisekundenbereich * *************************************/ void Delayms (unsigned int time) { volatile unsigned long tickertime; volatile unsigned int Count; Count = time / 5; tickertime = GetTicker (); while ( (tickertime + (unsigned long)Count) > GetTicker () ) CLRWDT (); } /************************************* * * Hol die Biturst aus dem MAX-Dödel * *************************************/ void LeseTemperatursensor (char Sensor) { #define SensorFehler -100 unsigned long TSensorenBitMaske; int i; int TTemp; TemperaturCLK = 0; DelayUs (100); // Chipselect erzeugen if (Sensor == SensorBoden1) TemperaturCS0 = 0; if (Sensor == SensorBoden2) TemperaturCS1 = 0; if (Sensor == SensorPlatine) TemperaturCS2 = 0; if (Sensor == SensorDampf) TemperaturCS3 = 0; DelayUs (100); // sprintf (outpbuf, "Sensor %d:", Sensor); // if (Sensor == SensorPlatine) print (outpbuf); // Sensor abfragen, alle 32 Bit rüberlutschen SensorRohwort [Sensor] = 0; for (i=31; i > 0; i--) { TemperaturCLK = 1; TSensorenBitMaske = ((long)1 << (long)i); // Bitmaske erzeugen if (TemperaturSO) SensorRohwort [Sensor] |= TSensorenBitMaske; // Bit reinholen /* if (Sensor == SensorPlatine) { if (TemperaturSO) print ("1"); else print ("0"); } */ TemperaturCLK = 0; DelayUs (100); // Nächste Flanke erzeugen } //----------------------------- // Chipselect wieder lahmlegen //----------------------------- TemperaturCS0 = 1; TemperaturCS1 = 1; TemperaturCS2 = 1; TemperaturCS3 = 1; //--------------------------- // Dekodierung Thermoelement //--------------------------- TSensorenBitMaske = SensorRohwort [Sensor] & (unsigned long)0xFFFC0000; // Thermoelementtemperatur ausmaskieren TSensorenBitMaske = (TSensorenBitMaske >> (unsigned long)18); // Rechtsbündig machen TTemp = (int)TSensorenBitMaske; // An int übergeben // Temperatur [Sensor] = (int)TSensorenBitMaske; // An int übergeben /* Gifft nich, we hebt nur oever null!!! //-------------------------------------------- // Bei negativen Werten 2er-Komplement bilden //-------------------------------------------- if (TTemp & 0b0010000000000000) { TTemp |= 0b1100000000000000; // Negativ angleichen TTemp = ~Temperatur [Sensor]; TTemp --; TTemp *= -1; } */ // Auflösung liegt in 0.25°C-Schritten vor TTemp /= 4; // Drahtbruch und Co? /* if (SensorRohwort [Sensor] & 0b111) Temperatur [Sensor] = SensorFehler; else */ if (TTemp < 10) TTemp = SensorFehler; else if (TTemp > 300) TTemp = SensorFehler; //-------------------------- // In Ringpuffer übernehmen //-------------------------- Temperaturpuffer [Temperaturpufferzeiger][Sensor] = TTemp; // Ringpuffer /* if (Sensor == SensorPlatine) { sprintf (outpbuf, " = %d Grad\n\r", TTemp); print (outpbuf); } */ } /***************** * * Timerroutine * *****************/ void isr_Timer1 (void) { //-------------------- // Timer 1 Überlauf ? //-------------------- if (TMR1IF) { //--------------- // Zeitsteuerung //--------------- Systemticker (); // Isses mal wieder soweit????? TemperaturLeseZaehler++; if (TemperaturLeseZaehler > TemperaturLeseZaehlerMax) { TemperaturLeseZaehler = 0; TemperaturLeseFlag = TRUE; SekundenTicker++; } //------------------- // Ablauf alle 5 ms //------------------- TMR1H=0xE7; // n = 2^16 - t [s] * 625000 TMR1L=0x96; // Timer 1 neu vorladen (0xE796 = 5 ms) TMR1IF=0; // Clear Interrupt-Flag } // From Timer 1 Überlauf } /*************** * * Zentrale ISR * ***************/ interrupt void INT_ (void) { isr_Timer1 (); isr_usart (); //-------------------- // Drehgeber benutzt? //-------------------- if (INT0IF) { if (DrehgeberRechts) KurbelCounter++; else KurbelCounter--; INT0IF = 0; } return; // Zurück zum Hauptprogramm } /***************** * * Wo stehen wir? * *****************/ void ZeigeMesswerte (void) { // Aktuelle Messwerte in °C // SensorFehler -100 if (Temperatur [SensorBoden1] != SensorFehler) sprintf (outpbuf, "B1:%03d", Temperatur [SensorBoden1]); else sprintf (outpbuf, "B1:---"); lcd_print (0, 2, outpbuf); lcd_putch (0xDF); lcd_putch ('C'); if (Temperatur [SensorBoden2] != SensorFehler) sprintf (outpbuf, "B2:%03d", Temperatur [SensorBoden2]); else sprintf (outpbuf, "B2:---"); lcd_print (11, 2, outpbuf); lcd_putch (0xDF); lcd_putch ('C'); if (Temperatur [SensorPlatine] != SensorFehler) sprintf (outpbuf, " P:%03d", Temperatur [SensorPlatine]); else sprintf (outpbuf, " P:---"); lcd_print (0, 3, outpbuf); lcd_putch (0xDF); lcd_putch ('C'); if (Temperatur [SensorDampf] != SensorFehler) sprintf (outpbuf, " D:%03d", Temperatur [SensorDampf]); else sprintf (outpbuf, " D:---"); lcd_print (11, 3, outpbuf); lcd_putch (0xDF); lcd_putch ('C'); // sprintf (outpbuf, "%03d", SekundenTicker); // lcd_print (17, 0, outpbuf); } /************************************ * * Was krieg ich hier für mein Geld? * ************************************/ void StartBildschirm (void) { // Aktuelle Werte rausrotzen ZeigeMesswerte (); // Bedienmenü lcd_print (4, 1, "Konfigurieren"); lcd_print (8, 0, "Start"); // Position des Cursors if (StartMenuePos == 0) { lcd_print (0, 0, "->"); lcd_print (0, 1, " "); } else { lcd_print (0, 0, " "); lcd_print (0, 1, "->"); } } /*************************** * * Initialisierungsroutinen * ***************************/ void sysinit (void) { //-------------------- // IO-Ports klarmachen //-------------------- // Alle Ports initialisieren bzw. auf Null setzen PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; // Ein- Ausgangsdefinitionen, 0 = Output / 1 Input, siehe Schaltplan TRISA = 0b00000000; // TRISB = 0b00000111; // TRISC = 0b00100000; // TRISD = 0b00000000; // Alle Ausgang TRISE = 0b00000000; // //-------------------------- // AD-Wandler-Einstellungen //-------------------------- ADCON0 = 0x00; ADCON1 = 0x07; //------------ // Timer-Init //------------ TMR1IE=1; // enable Interrupt of TMR1 T1CON=49; // TMR1IP = 0; // Niedrige Priorität //--------------------- // Drehgeber-Interrupt //--------------------- INTEDG0 = 0; // Interrupt auf fallender Flanke INT0IE = 1; //-------------------- // Alle Interrupts an //-------------------- // IPEN = 1; PEIE=1; // Peripherie Int=on GIE=1; // Define Interupts //-------------------- // Sellerie anreissen //-------------------- UART_Init (); print ("Start Loeterine I\n\r"); //----------------------------- // Glotzn uff du Arschkrampe ! //----------------------------- lcd_init (); lcd_clear (); //---------------------- // Begrüßungsbildschirm //---------------------- Delayms (100); strcpy (outpbuf,"Loeterine I\0"); lcd_print (5,1, outpbuf); strcpy (outpbuf,"(C) Finger 2015\0"); lcd_print (2,2, outpbuf); Delayms (1000); lcd_clear (); // Nu geitdat los hia! StartBildschirm (); // Kofigurationsdaten laden TemperaturPunkt1 = EEPromLesenInt (0); ZeitPunkt1 = EEPromLesenInt (2); ZeitPlateau = EEPromLesenInt (4); TemperaturAbbruch = EEPromLesenInt (6); // Auf Plausibilität prüfen, ggf. Defaultwerte setzen if ((TemperaturPunkt1 > 300) || (TemperaturPunkt1 < 30) ) TemperaturPunkt1 = 110; if ((ZeitPunkt1 > 1000) || (ZeitPunkt1 < 10) ) ZeitPunkt1 = 360; if ((ZeitPlateau > 1000) || (ZeitPlateau < 1) ) ZeitPlateau = 120; if ( (TemperaturAbbruch > 300) || (TemperaturAbbruch < 100) ) TemperaturAbbruch = 250; } /************************************ * * Was krieg ich hier für mein Geld? * ************************************/ void KonfigBildschirm (void) { // Aktuelle Messwerte in °C sprintf (outpbuf, "Rampe %03d", TemperaturPunkt1); lcd_print (0, 0, outpbuf); lcd_putch (0xDF); lcd_putch ('C'); sprintf (outpbuf, " %03ds ", ZeitPunkt1); lcd_print (14, 0, outpbuf); sprintf (outpbuf, "Plateau %03ds ", ZeitPlateau); lcd_print (0, 1, outpbuf); sprintf (outpbuf, "Ende %03d", TemperaturAbbruch); lcd_print (0, 2, outpbuf); lcd_putch (0xDF); lcd_putch ('C'); lcd_print (0, 3, " Fertig"); // Mann, was für ein räudiges Konstrukt... if (KonfigMenuePos == 0) { lcd_print (6, 0, "*");lcd_print (14, 0, " ");lcd_print (8, 1, " ");lcd_print (5, 2, " ");lcd_print (0, 3, " "); } if (KonfigMenuePos == 1) { lcd_print (6, 0, " ");lcd_print (14, 0, "*");lcd_print (8, 1, " ");lcd_print (5, 2, " ");lcd_print (0, 3, " "); } if (KonfigMenuePos == 2) { lcd_print (6, 0, " ");lcd_print (14, 0, " ");lcd_print (8, 1, "*");lcd_print (5, 2, " ");lcd_print (0, 3, " "); } if (KonfigMenuePos == 3) { lcd_print (6, 0, " ");lcd_print (14, 0, " ");lcd_print (8, 1, " ");lcd_print (5, 2, "*");lcd_print (0, 3, " "); } if (KonfigMenuePos == 4) { lcd_print (6, 0, " ");lcd_print (14, 0, " ");lcd_print (8, 1, " ");lcd_print (5, 2, " ");lcd_print (0, 3, "*"); } sprintf (outpbuf, "%d ", KonfigMenuePos); print (outpbuf); } //----------------------------------------------------- // Zahleneingabe per Drehgeber, alle Werte dreistellig //----------------------------------------------------- void Zahleneingabe (char Pos) { int xpos, ypos; // Eingabeposition int Wert; // Zwischengespeicherter Wert char Zahleneingaelaeuft = TRUE; int min, max; if (Pos == 0) { min = 30; max=230; xpos = 7; ypos = 0; Wert = TemperaturPunkt1; } if (Pos == 1) { min = 5; max = 500; xpos = 15; ypos = 0; Wert = ZeitPunkt1; } if (Pos == 2) { min = 5; max = 500; xpos = 9; ypos = 1; Wert = ZeitPlateau; } if (Pos == 3) { min = 200; max=250; xpos = 6; ypos = 2; Wert = TemperaturAbbruch; } sprintf (outpbuf, "Eingabe: %d @ X:%d Y:%d\n\r", Pos, xpos, ypos); print (outpbuf); lcd_cursor_on (TRUE); lcd_cursorpos (ypos, xpos); //-------------------- // Knöppche gedrüggt? //-------------------- Zahleneingaelaeuft = TRUE; KurbelCounter = 0; KurbelcounterAlt = 0; while (Zahleneingaelaeuft) { CLRWDT (); // Gekurbelt? if (KurbelCounter != KurbelcounterAlt) { if (KurbelCounter < KurbelcounterAlt) Wert++; else Wert--; if (Wert > max) Wert = max; if (Wert < min) Wert = min; sprintf (outpbuf, "Wert: %d @ X:%d Y:%d\n\r", Wert, xpos, ypos); print (outpbuf); sprintf (outpbuf, "%03d", Wert); lcd_print (xpos, ypos, outpbuf); lcd_cursorpos (ypos, xpos); KurbelcounterAlt = KurbelCounter; } // Von if (KurbelCounter != KurbelcounterAlt) // Gedrückt? if (!DrehgeberPush) { while (!DrehgeberPush) Delayms (50); // Warten, bis losgelassen Zahleneingaelaeuft = FALSE; } } // Von while (Zahleneingaelaeuft) lcd_cursor_on (FALSE); // Wert wieder zurückliefern if (Pos == 0) { TemperaturPunkt1 = Wert; } if (Pos == 1) { ZeitPunkt1 = Wert; } if (Pos == 2) { ZeitPlateau = Wert; } if (Pos == 3) { TemperaturAbbruch = Wert; } // Speicher mal den Dreck... EEPromSchreibenINT (0, TemperaturPunkt1); EEPromSchreibenINT (2, ZeitPunkt1); EEPromSchreibenINT (4, ZeitPlateau); EEPromSchreibenINT (6, TemperaturAbbruch); print ("Gespeichert\n\r"); } /********************* * * Stell schon ein ! * *********************/ void Konfigmenue (void) { lcd_clear (); KonfigMenuePos = 4; // Cursor steht auf "Fertig" KurbelCounter = 0; // Drehbewegungen abfragen KurbelcounterAlt = 0; KonfigBildschirm (); while (FlagKonfigMenue) { CLRWDT (); //----------------------- // Wurde am Rad gedreht? //----------------------- if (KurbelCounter != KurbelcounterAlt) { if (KurbelCounter < KurbelcounterAlt) KonfigMenuePos++; else KonfigMenuePos--; // Rauf und runter.... if (KonfigMenuePos < 0) KonfigMenuePos = 4; // Grenzen beachten if (KonfigMenuePos > 4) KonfigMenuePos = 0; // Grenzen beachten KonfigBildschirm (); // Änderungen anzeigen KurbelcounterAlt = KurbelCounter; } // Von if (KurbelCounter != KurbelcounterAlt) //-------------------- // Knöppche gedrüggt? //-------------------- if (!DrehgeberPush) { while (!DrehgeberPush) Delayms (50); // Warten, bis losgelassen // Zahleneingabe an der Cursorposition oder weg hier... if (KonfigMenuePos != 4) Zahleneingabe (KonfigMenuePos); if (KonfigMenuePos == 4) FlagKonfigMenue = FALSE; } } // Von while (FlagKonfigMenue) } /*********************************** * * Schaltet die Heizung an oder aus * ***********************************/ void Regelung (int Sensor, int Sollwert) { #define HYSTERESE 2 if ((Temperatur [Sensor] - HYSTERESE) < Sollwert) { Heizung = 1; Delayms (100); Temperreicht = FALSE; } else // Mistkacke if ((Temperatur [Sensor] + HYSTERESE) > Sollwert) { Heizung = 0; Delayms (100); Temperreicht = TRUE; } } /************************************** * * Holt tagesaktuelle Wettquoten rein, * rodet Rüben, kocht Kaffee und * schaut mal fix aufs Thermometer * **************************************/ void Ladetemperaturen (void) { int i,j; unsigned long TempWert; // Zeit abgelaufen? Dann leg los. Sonst: verpiss dich! if (!TemperaturLeseFlag) return; TemperaturLeseFlag = FALSE; //-------------------------------------------- // Aktuelle Temperaturen reinsaugen *Schlürf* //-------------------------------------------- for (i=0; i < 4; i++) LeseTemperatursensor (i); //--------------------------------------------------------------------- // Werte in Ringpuffer schreiben und schwimmenden Mittelwert errechnen //--------------------------------------------------------------------- Temperaturpufferzeiger++; if (Temperaturpufferzeiger >= TemperaturpufferSize) Temperaturpufferzeiger = 0; //---------------------- // Mittelwert errechnen //---------------------- for (i=0; i < 4; i++) { TempWert = 0; for (j=0; j < TemperaturpufferSize; j++) TempWert += Temperaturpuffer [j][i]; Temperatur [i] = (int)TempWert / TemperaturpufferSize; } } /************************** * * Nu löt endlich du Sau! * **************************/ void LoetImperativ (void) { int Status; // Wo sind wir gerade? int Sollwert; // Aktueller Sollwert der Temperatur float m, b; // Geradenparameter int Rampenzeit; // Zeit der erste Rampe int Plateauzeit;// Zeit für den geraden Teil int GesamtZeit; // Wie lange sind wir dabei? unsigned long ZeitZaehler; // Zeitmessung #define STATUSRAMPE 1 #define STATUSPLATEAU 2 #define STATUSENDHEIZEN 3 lcd_clear (); KurbelCounter = 0; // Drehbewegungen abfragen KurbelcounterAlt = 0; GesamtZeit = 0; Status = STATUSRAMPE; // Wir fangen mit der Rampe an Sollwert = Temperatur [SensorPlatine]; // Hier gehts los ZeitZaehler = GetTicker (); // Geradeparameter errechnen für die erste Rampe b = Sollwert; m = (TemperaturPunkt1 - b) / ZeitPunkt1; Rampenzeit = 1; while (FlagLoeten) { CLRWDT (); // Lutsch, saug, sabber... Ladetemperaturen (); // Aktuelle Werte rausrotzen ZeigeMesswerte (); sprintf (outpbuf, "Soll:%03d Zeit:%ds", Sollwert, GesamtZeit); lcd_print (0, 0, outpbuf); if (Status == STATUSRAMPE) lcd_print (0, 1, "Rampe"); if (Status == STATUSPLATEAU) lcd_print (0, 1, "Plateau"); if (Status == STATUSENDHEIZEN) lcd_print (0, 1, "Endheizen"); //----------------------- // Temperaturen anfahren //----------------------- if (Status == STATUSRAMPE) { Regelung (SensorPlatine, Sollwert); // Heizung steuern print ("1"); // Aktuelle Zeit bestellen if ((ZeitZaehler + 80) < GetTicker ()) { Sollwert = (int)(((float)Rampenzeit * m) + b); // Wo solls hingehen? ZeitZaehler = GetTicker (); Rampenzeit++; GesamtZeit++; } // Von if ((ZeitZaehler + 80) < GetTicker ()) // Sind wir fertig? if ( (Rampenzeit > ZeitPunkt1) && (Temperreicht) ) // Zeit abgelaufen? { Plateauzeit = 0; Status = STATUSPLATEAU; } // Von if (Rampenzeit > ZeitPunkt1) // Zeit abgelaufen? } // Von if (Status == STATUSRAMPE) //----------------------- // Plateau //----------------------- if (Status == STATUSPLATEAU) { Regelung (SensorPlatine, Sollwert); // Heizung steuern print ("2"); // Aktuelle Zeit bestellen if ((ZeitZaehler + 80) < GetTicker ()) { ZeitZaehler = GetTicker (); Plateauzeit++; GesamtZeit++; if (Plateauzeit > ZeitPlateau) // Zeit abgelaufen? { Plateauzeit = ZeitPlateau; Status = STATUSENDHEIZEN; Sollwert = TemperaturAbbruch; } // if (Plateauzeit > ZeitPunkt2) // Zeit abgelaufen? } // Von if ((ZeitZaehler + 80) < GetTicker ()) } // Von if (Status == STATUSPLATEAU) //------- // Löten //------- if (Status == STATUSENDHEIZEN) { Regelung (SensorPlatine, Sollwert); // Heizung steuern print ("3"); // Aktuelle Zeit bestellen if ((ZeitZaehler + 80) < GetTicker ()) { ZeitZaehler = GetTicker (); Plateauzeit++; GesamtZeit++; if (Temperatur [SensorPlatine] > Sollwert) // Warm genug jetzt? { FlagLoeten = FALSE; Heizung = 0; } } // Von if ((ZeitZaehler + 80) < GetTicker ()) } // Von if (Status == STATUSENDHEIZEN) //--------------------------------- // Überwachung der Bodentemperatur //--------------------------------- #define Grenztemperatur 250 if ( (Temperatur [SensorBoden1] > Grenztemperatur) || (Temperatur [SensorBoden2] > Grenztemperatur)) { // Notaus! FlagLoeten = FALSE; Heizung = 0; NotAusFlag = TRUE; print ("4"); } //--------------------------------------------------- // Wurde am Rad gedreht? Gruseliges Denglisch, oder? //--------------------------------------------------- if (KurbelCounter != KurbelcounterAlt) { FlagLoeten = FALSE; // Raus hier Heizung = 0; // Heizung abschalten print ("5"); } // Von if (KurbelCounter != KurbelcounterAlt) } // Von while (FlagLoeten) Heizung = 0; print ("6"); // Heizung aus } /************* * * Main * *************/ void main (void) { //---------------------- // System initialisieren //---------------------- sysinit (); //--------------- // Hauptschleife //--------------- while (1) { CLRWDT (); //----------------------- // Starten mit Hauptmenü //----------------------- lcd_clear (); StartBildschirm (); // Erster Bildschirm FlagHauptMenue = TRUE; KurbelCounter = 0; // Drehbewegungen abfragen KurbelcounterAlt = 0; // while (1) { print ("."); CLRWDT (); Delayms (50); } while (FlagHauptMenue) // Hier bleiben wir erst einmal { CLRWDT (); print ("9"); // Lutsch, saug, sabber... Ladetemperaturen (); //--------------------------------------------------- // Wurde am Rad gedreht? Gruseliges Denglisch, oder? //--------------------------------------------------- if (KurbelCounter != KurbelcounterAlt) { if (StartMenuePos == 0) StartMenuePos = 1; else StartMenuePos = 0; KurbelcounterAlt = KurbelCounter; } // Von if (KurbelCounter != KurbelcounterAlt) // Laufend Messwerte etc. anzeigen StartBildschirm (); Delayms (10); // Wollen wir etwa Äktschn? Hol mal den Schwarzenegger... if (!DrehgeberPush) { while (!DrehgeberPush) Delayms (50); // Warten, bis losgelassen if (StartMenuePos == 1) FlagKonfigMenue = TRUE; // Konfigurationsmenü starten if (StartMenuePos == 0) FlagLoeten = TRUE; // Löten starten FlagHauptMenue = FALSE; } } // Von while (FlagHauptMenue) //----------------------------------------- // Hier gelandet ist also Aktion angesagt //----------------------------------------- if (FlagKonfigMenue) Konfigmenue (); if (FlagLoeten) LoetImperativ (); //---------------- // Notabschaltung //---------------- if (NotAusFlag) { lcd_clear (); lcd_print (0, 0, "Notabschaltung"); lcd_print (0, 1, "erfolgt!!!"); while (1) { Ladetemperaturen (); ZeigeMesswerte (); CLRWDT (); } } // von if (NotAusFlag) } // Von while (1) } // That´s all folks !