Heizkoerper Thermostat Programm: Unterschied zwischen den Versionen

Aus Ethersex_Wiki
Wechseln zu: Navigation, Suche
K
K
Zeile 1: Zeile 1:
 
 
Mein Aufbau:
 
Mein Aufbau:
  
Zeile 50: Zeile 49:
  
  
/* jump to bootloader = 1024 words  */
+
/* jump to bootloader = 512 words  */
 
void (*jump_boot)(void) = (void *)0x1E00;
 
void (*jump_boot)(void) = (void *)0x1E00;
  

Version vom 14. Mai 2010, 15:50 Uhr

Mein Aufbau:

Jeweils 2 Thermy Heizkörper Thermostate an ein Pollin AVR-NET-IO Board, Verbindung mittels TTL (RS232) - ZBUS, Da bei der schaltung des Thermy's der Lichtschranken eingang auf die RS232 TX Leitung gelegt wurde, habe ich hier eine veränderung der schaltung vorgenommen, in dem ich die eine leiterbahn durchtrenne, und eine brücke löte um als Lichtschranken Eingang den PE4 Kontakt nutzen zu können. Des weiteren habe ich den 32Khz Uhrenquarz durch einen größeren 8MHz Quarz ersetzt, mit diesem gibt es keine stabilitäts probleme bei der datenübertragung durch ungenauigkeit des internen oszilators, sowie der abweichung bei temperatur veränderung.


Bilder zu der modifikation, sowie verkabelung folgenn och....




// ################################################################################
// # This program is free software; you can redistribute it and/or modify it      #
// # under the terms of the GNU General Public License (either version 2 or       #
// # version 3) as published by the Free Software Foundation.                     #
// #                                                                              #
// # This program is distributed in the hope that it will be useful,              #
// # but WITHOUT ANY WARRANTY; without even the implied warranty of               #
// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
// # GNU General Public License for more details.                                 #
// #                                                                              #
// # You should have received a copy of the GNU General Public License            #
// # along with this program; if not, write to the Free Software                  #
// # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                    #
// #                                                                              #
// # For more information on the GPL, please go to:                               #
// # http://www.gnu.org/copyleft/gpl.html                                         #
// #                                                                              #
// #                                                                              #
// # Programm Erstellung:                                                         #
// #   Copyright (C) 2009-2010 - Michael Schultz <ethersex@keyb.de>               #
// #                                                                              #
// ################################################################################

/* Fuses:       Extended        0xFF
 *              High            0x9A
 *              Low             0xFF
 *http://frank.circleofcurrent.com/fusecalc/fusecalc.php?chip=atmega169&LOW=FF&HIGH=9A&EXTENDED=FF&LOCKBIT=FF
 */


#include <hardware/lcd/hr20.h>
#include <hardware/adc/hr20-temp.h>



/* jump to bootloader = 512 words  */
void (*jump_boot)(void) = (void *)0x1E00;


static uint8_t RXLine ;

static uint16_t Message = 0 ;
static uint16_t RingCount = 0 ;
static uint16_t Int0Cnt = 0 ;
static uint16_t Int0CntOld = 0 ;
static uint16_t Int0RingCountOld = 0 ;
static uint16_t Int0StopPos = 900 ;

static uint8_t t1 ;             // Taste, Links,  Auto/Manu
static uint8_t t2 ;             // Taste, Mitte,  Prog
static uint8_t t3 ;             // Taste, Rechts, Temp
static uint8_t t4 ;
static uint8_t t5 ;
static uint8_t Counter1 = 0 ;

static uint16_t Counter2 = 0 ;

static uint8_t rotate = 5 ;

static uint8_t DisplayMode = 1;         //      Anzeige Modus
static uint8_t DisplayChar0 ;
static uint8_t DisplayChar1 ;
static uint8_t DisplayChar2 ;
static uint8_t DisplayChar3 ;
static uint8_t MotorRun = 0;
static uint16_t BattSpannung;
static uint16_t TempGrad;
//########################################################################################################################
void motor_off() {
        PORTG &= ~_BV(PG3);             //      PORTG(PG3) = 0          Motor Aus
        PORTG &= ~_BV(PG4);             //      PORTG(PG4) = 0          Motor Aus
        MotorRun = 0;
}
void motor_open() {
        PORTG &= ~_BV(PG3);             //      PORTG(PG3) = 0          Motor Vorwärts ( Ventil Auf )
        PORTG |=  _BV(PG4);             //      PORTG(PG4) = 1          Motor Vorwärts ( Ventil Auf )
        MotorRun = 1;
        Int0RingCountOld = RingCount ;
        Int0Cnt = 0;
        Int0CntOld = 0;
}
void motor_close() {
        PORTG |=  _BV(PG3);             //      PORTG(PG3) = 1          Motor Rückwärts ( Ventil Zu )
        PORTG &= ~_BV(PG4);             //      PORTG(PG4) = 0          Motor Rückwärts ( Ventil Zu )
        MotorRun = 1;
        Int0RingCountOld = RingCount ;
        Int0Cnt = 0;
        Int0CntOld = 0;
}
void motor_hang_check() {
        if ( RingCount >= ( Int0RingCountOld + 6 ) || Int0Cnt > Int0StopPos ) {
                motor_off();
        } else {
                if ( Int0Cnt > Int0CntOld ) {
                        Int0RingCountOld = RingCount ;
                        Int0CntOld = Int0Cnt ;
                }
        }
        Counter2 = Int0Cnt;
}
//########################################################################################################################
#include <protocols/ecmd/ecmd-base.h>
int16_t parse_cmd_motor_stop(char *cmd, char *output, uint16_t len) {
        while (*cmd == ' ')
        cmd++;
        if (*cmd == '\0') {
                return ECMD_FINAL(snprintf_P(output, len, PSTR("%d"), Int0StopPos));
        } else {
                uint16_t NewInt0StopPos = strtoul(cmd, NULL, 10);
                if (!NewInt0StopPos)
                        return ECMD_ERR_PARSE_ERROR;
                Int0StopPos=NewInt0StopPos;
                return ECMD_FINAL_OK;
        }
}
int16_t parse_cmd_motor_pos(char *cmd, char *output, uint16_t len) {
        return ECMD_FINAL(snprintf_P(output, len, PSTR("%d"), Int0Cnt));
}
int16_t parse_cmd_motor_open(char *cmd, char *output, uint16_t len) {
        motor_open();
        return ECMD_FINAL_OK;
}
int16_t parse_cmd_motor_close(char *cmd, char *output, uint16_t len) {
        motor_close();
        return ECMD_FINAL_OK;
}
//########################################################################################################################
CONTROL_START

dnl     ECMD_GLOBAL(EcmdVal, 0, uint16_t);

        THREAD(DisplayOut)
                BattSpannung=HR20_GET_BATT ();
                TempGrad=hr20_temp_get ();

                switch(DisplayMode) {
                case 1: // Anzeige Datum und uhrzeit
                        DisplayChar3=((datetime.hour / 10) % 10);
                        DisplayChar2=(datetime.hour % 10);
                        DisplayChar1=((datetime.min / 10) % 10);
                        DisplayChar0=(datetime.min % 10);
                        break;
                case 2: // Anzeige Batterie Spannung
                        DisplayChar3=HR20_LCD_CHAR_SPACE;
                        DisplayChar2=((BattSpannung / 100) % 10);
                        DisplayChar1=((BattSpannung / 10)  % 10);
                        DisplayChar0=( BattSpannung        % 10);
                        LCD_SEG_CLEAR (LCD_SEG_COL1);
                        LCD_SEG_SET   (LCD_SEG_COL2);
                        break;
                case 3: // Anzeige Temperatur
                        DisplayChar3=((TempGrad / 100) % 10);
                        DisplayChar2=((TempGrad / 10)  % 10);
                        DisplayChar1=( TempGrad        % 10);
                        DisplayChar0=HR20_LCD_CHAR_DEG;
                        LCD_SEG_CLEAR (LCD_SEG_COL1);
                        LCD_SEG_SET   (LCD_SEG_COL2);
                        break;
                case 4: // Counter2 wert anzeige
//                      DisplayChar3=HR20_LCD_CHAR_SPACE;
                        DisplayChar3=((Counter2 / 1000) % 10);
                        DisplayChar2=((Counter2 / 100) % 10);
                        DisplayChar1=((Counter2 / 10) % 10);
                        DisplayChar0=(Counter2 % 10);
                }
                if ( DisplayMode >= 1 ) {
                        LCD_SEG_TOGGLE (LCD_SEG_COL1);
                        LCD_SEG_TOGGLE (LCD_SEG_COL2);
                        hr20_lcd_putchar(3, DisplayChar3);
                        hr20_lcd_putchar(2, DisplayChar2);
                        hr20_lcd_putchar(1, DisplayChar1);
                        hr20_lcd_putchar(0, DisplayChar0);
                }
                WAIT(1);
        THREAD_END(DisplayOut)

        ON STARTUP DO

                // vorbereitung für tasten und wahlrad
                DDRB = 0;
                PORTB = (1<<PB7) | (1<<PB6) | (1<<PB3) | (1<<PB2) | (1<<PB1) | (1<<PB0);

                // Lichtschranke vorbereiten
                // DDRE   &= ~_BV(PE4);         // DDRE(PE4) = 0        Eingang Schalten für lichschranken ausgang
                // PORTE  &= ~_BV(PE4);         // PORTE(PE4) = 0       Pullup deaktivieren für lichschranken ausgang
                // DDRE   |=  _BV(PE2);         // DDRE(PE2) = 1        Lichtschranke pinne, vorbereiten
                // DDRE   |=  _BV(PE3);         // DDRE(PE3) = 1        Lichtschranke pinne, vorbereiten
                // PORTE  |=  _BV(PE2);         // PORTE(PE2) = 1       Lichtschranke aktivieren ( port output and high )
                // PORTE  |=  _BV(PE3);         // PORTE(PE3) = 1       Lichtschranke aktivieren ( port output and high )
                // PCMSK0 |=  _BV(PCINT4);              // PCMSK0(PCINT4) = 1   interrupt für den pin aktivieren
                // EIMSK  |=  _BV(PCIE0);               // EIMSK(PCIE0) = 1     interrupt generell f.r pereferie 0 aktivieren

                // Interrupt für Tasten und Wahlrad
                // PCMSK1 |=  _BV(PCINT12);     dnl Interrupt aktivierung f.r wahlrad
                // PCMSK1 |=  _BV(PCINT13);     dnl Interrupt aktivierung f.r wahlrad
                // EIMSK  |=  _BV(PCIE1);               //      EIMSK(PCIE1) = 1        Pin Change Interrupt Enable 1

                DDRE   = (1<<PE3)     | (1<<PE2);
                PORTE  = (1<<PE3)     | (1<<PE2);
                PCMSK0 = (1<<PCINT4);
                PCMSK1 = (1<<PCINT12) | (1<<PCINT13);
                EIMSK  = (1<<PCIE0)   | (1<<PCIE1);

                RXLine = 1 ;

                TCP_CONNECT(10.2.0.33, 95, message_handler);

                clock_set_time(1273785514);

                THREAD_START(DisplayOut)
        END

        RingCount ++ ;
        if ( RingCount >= 32768 ) { RingCount = 0 ; }

        TCP_HANDLER_PERSIST(message_handler)
        for (;;) {
                if ( MotorRun == 0 ) {
                        TCP_SEND("Message=%d BattSpannung=%d TempGrad=%d\n", Message, BattSpannung, TempGrad);
                }
                        Message ++;
                        if ( Message >= 32768 ) { Message = 0 ; }
                WAIT(60);
        }
        TCP_HANDLER_END();
        //########################################
        if (!(PINB & 0b00000001)) {
                t1 ++ ;
                if ( t1 >= 251 ) { t1 = 250 ; }
        } else {
                t1=0 ;
        }
        if (!(PINB & 0b00000010)) {
                t2 ++ ;
                if ( t2 >= 251 ) { t2 = 250 ; }
        } else {
                t2=0 ;
        }
        if (!(PINB & 0b00000100)) {
                t3 ++ ;
                if ( t3 >= 251 ) { t3 = 250 ; }
        } else {
                t3=0 ;
        }
        //########################################
        // Jump to Bootloader
        if ( t1 == 100 && t3 == 100 ) {
                jump_boot();
        }
        // motor_open
        if ( t1 >= 10 ) {
                motor_open();
        }
        // motor_close
        if ( t3 >= 10 ) {
                motor_close();
        }
        //
        if ( t2 >= 10 ) {
                DisplayMode ++;
                if ( DisplayMode >= 5 ) { DisplayMode = 0 ; }
                t2 = 0;
        }
        if ( MotorRun == 1 ) { motor_hang_check(); }
        //########################################
CONTROL_END
//########################################################################################################################
// Interrupt für dir motor Lichtschranke
ISR(PCINT0_vect) {
        Int0Cnt ++;
}
//########################################################################################################################
// Interrupt für Tasten und Wahlrad
ISR(PCINT1_vect) {
        if (!(PINB & 0b00010000)) {     // PB4 (entprellt)
                t4 = 1 ;
                if ( t4 >= 251 ) { t4 = 250 ; }
        } else {
                t4 = 0 ;
        }
        if (!(PINB & 0b00100000)) {     // PB5
                t5 = 1 ;
                if ( t5 >= 251 ) { t5 = 250 ; }
        } else {
                t5 = 0 ;
        }
        if ( t4 == 1 && t5 == 0 && rotate == 5 ) { rotate = 6 ; }
        if ( t4 == 1 && t5 == 1 && rotate == 6 ) { rotate = 7 ; }
        if ( t4 == 0 && t5 == 1 && rotate == 7 ) { rotate = 8 ; }
        if ( t4 == 0 && t5 == 0 && rotate == 8 ) { rotate = 5 ; Counter1 ++ ; }
        if ( t4 == 0 && t5 == 1 && rotate == 5 ) { rotate = 4 ; }
        if ( t4 == 1 && t5 == 1 && rotate == 4 ) { rotate = 3 ; }
        if ( t4 == 1 && t5 == 0 && rotate == 3 ) { rotate = 2 ; }
        if ( t4 == 0 && t5 == 0 && rotate == 2 ) { rotate = 5 ; Counter1 -- ; }
}
//########################################################################################################################

/*
  -- Ethersex META --
  ecmd_feature(motor_open, "motor open", Moror Open)
  ecmd_feature(motor_close, "motor close", Moror Close)
  ecmd_feature(motor_stop, "motor stop",[value], Display/Set the current thermy value.)
  ecmd_feature(motor_pos, "motor pos", Moror Pos)
*/