Exemplo n.º 1
0
// Soll-Laufzeit anpassen und Kalibrierkennung setzen
static void prepare_calibration(device_data_rolladen *p)
{
	if (p->kalibrieren) // bereits gesetzt?
	{
		// Unabhaengig vom Feature wird nach Reboot die Oben- oder Untenlage kalibriert:
		if(ROLLADEN_DIR_AUF == p->soll_dir)
		{
			canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("ro"));
			p->soll_laufzeit = ((int32_t)p->config.laufzeit * 150 / 100); // 100 = oben: hier 150% drauf: 200%
		}
		else // ROLLADEN_DIR_AB -> unten kalibrieren
		{
			canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("ru"));
			p->soll_laufzeit = -((int32_t) p->config.laufzeit * 50 / 100); // 0 = unten: hier 50% noch ins negative
		}
	}
	else if (p->config.feature & (1<<FEATURE_KALIBRIERUNG_OBEN))
	{
		if(ROLLADEN_DIR_AUF == p->soll_dir)
		{
			canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("eo"));
			p->soll_laufzeit = ((int32_t)p->config.laufzeit * 150 / 100); // 100 = oben: hier 150% drauf: 200%
			p->kalibrieren = 1;
		}
	}
	else // unten kalibrieren:
	{
		if(ROLLADEN_DIR_AB == p->soll_dir)
		{
			canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("eu"));
			p->soll_laufzeit = -((int32_t) p->config.laufzeit * 50 / 100); // 0 = unten: hier 50% noch ins negative
			p->kalibrieren = 1;
		}
	}
}
Exemplo n.º 2
0
static void rolladen_cmd_stop(device_data_rolladen *p)
{
	uint8_t pos = rolladen_get_position(p);
	if(pos == 0 || pos == 100) // untere oder obere Endlage erreicht?
	{
		// canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("r"));
		p->last_dir = !p->dir; // Richtungswechsel (1-Taster-Betrieb)
		p->change_dir_counter = -1; // abmelden (1-Taster-Betrieb)

		if(p->kalibrieren) calibration(p); // Endlage unten oder oben kalibrieren
	}
	else p->kalibrieren = 0;

	canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("dir=%d"), p->dir);
	canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("t=%d"), p->stoppuhr); // Stopp in 0=AUF, 1=ZU
	p->stoppuhr = 0;
	canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("lz=%d"), p->laufzeit);
	rolladen_send_changed_info(p, pos);

	p->soll_power = 0;
	p->exe_power = 1; // Halt-Auftrag: Power-Relais sofort aus

	p->soll_dir = ROLLADEN_DIR_AUF; // nur um das Relais abzuschalten
	// Wegen Dir-Umschaltung verzoegern?
	if (ROLLADEN_DIR_AB == p->dir)
	{
		p->blockingTimer = 5; // = 0,5 s (Dir-Relais sicher umschalten)
		p->exe_dir = 0; // erst nach Zeitablauf
	}
	// else Dir-Relais liegt schon richtig

	p->soll_laufzeit = -1; // kein Soll
}
Exemplo n.º 3
0
void configurePorts (void)
{
	uint8_t portindex = 0;
	uint8_t boardindex;
	uint8_t adr = 0;
	uint8_t port;
	uint8_t bank = 0; // A
	uint8_t numberOfInputs = 0;
	uint8_t numberOfOutputs = 0;
	for (boardindex=0; boardindex<MAXIMUM_NUMBER_OF_EXPANDER_BOARDS; boardindex++) // boardindex: Index auf je 4-Ports (ein IO-Board)
	{
		if (expBoard[boardindex] != 255)
		{
			for (port=0; port<4; port++)
			{
				if (isMCP23x17available(boardindex, adr))
				{
					expanderActive = true;
					if ((expBoard[boardindex] & (1<< port)) != 0) // als INPUT konfiguriert?
					{
						canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("i:%d-%d"), portindex, adr);
						expStartPins[portindex] = inBase + 8*numberOfInputs;
						configurePortAsInput (bank, adr);
						numberOfInputs++;
					}
					else // Bit ist 0, dann als OUTPUT konfiguriert:
					{
						canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("o:%d-%d"), portindex, adr);
						expStartPins[portindex] = outBase + 8*numberOfOutputs;
						configurePortAsOutput (bank, adr);
						numberOfOutputs++;
					}
				}
				else // Das Board (2 IC's) ist (sind) nicht ansprechbar:
				{
					expBoard[boardindex] = 255; // und wird daher aus der Konfiguration genommen
					canix_syslog_P (SYSLOG_PRIO_DEBUG, PSTR("!%d-%d,%d"), portindex, adr, boardindex);
			    	/* Sollte ein Softreset nicht reichen, dann hier muss ggf. einmal
			    	   die Versorgungsspannung des MCP23x17 abgeschaltet werden! */
				}

				portindex++;

				if (port==3) bank = 0; // fuer port 0
				if (port==1) {bank = 1; adr--;} // fuer port 2
				else adr++;
			}
		}
		else
		{
			adr += 2; // Board nicht konfiguriert
			portindex += 4;
		}
	}

}
Exemplo n.º 4
0
/* Hinweis: Wird diese Funktion ohne Pullups an IN0 und IN1 ausgefuehrt,
   so kommt es zu wdt-Resets. Daher ports-Device nur konfigurieren,
   wenn auch ein IO-Expander angeschlossen ist! */
void ports_init (device_data_ports *p, eds_block_p it)
{
	if (portsDeviceCreated == true)
	{
		canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("Additional ports configuration ignored"));
		return;
	}
	portsDeviceCreated = true; // There can be only ONE ports Device
	expanderActive = false;

	i2c_init (); // SDA/SDL-Pins sind ueber I2C-master-Lib ATmegatypabhaengig festgelegt

	uint8_t i;
	for (i=0; i<4*MAXIMUM_NUMBER_OF_EXPANDER_BOARDS; i++)
	{
		valuesOfPortsOnExpBoard[i] = 0;
		previousValuesOfPortsOnExpBoard[i] = 255;
	}

	expBoard = &p->config.expander0; // z.B. 0,255,15,15 (4x OUT, -, 4x IN, 4x IN)

	if (p->config.base == 128)
	{
		// Zur Erzeugung der Startpinnummern (Ingo's Nummerierung):
		outBase = 12;
		inBase = 16;
		// Bsp.:expStartPins[] = {12,20,28,36, 44,52,60,68, 16,24,32,40, 48,56,64,72};
	}
	else // Christoph's aktuelle Nummerierung:
	{
		outBase = inBase = 32;
	}

	configurePorts ();
}
Exemplo n.º 5
0
static inline uint8_t getMittlererWaermebedarf(device_data_zentralheizungspumpe *p)
{
	uint16_t gesamtWaermebedarf = 0;
	uint8_t i = 0;
	uint8_t n = 0;
	for(n=0; n<MAX_ANZ_HEIZUNGEN; n++)
	{
		if (p->heizung[n].waermebedarf > 0)
		{
			gesamtWaermebedarf += p->heizung[n].waermebedarf;
			i++;
		}
	}

	if(gesamtWaermebedarf == 0)
	{
		return 0;
	}
	else
	{
		uint8_t mittlereWaermebedarf = gesamtWaermebedarf / i;
		canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("WB_%d/%i=%d"), gesamtWaermebedarf, i, mittlereWaermebedarf);
		return mittlereWaermebedarf;
	}
}
Exemplo n.º 6
0
static inline uint8_t getMCP23017outportpin (uint8_t n, uint8_t * pportindex)
{
	uint8_t portindex = 0;
	uint8_t boardindex;
	uint8_t port;
	for (boardindex=0; boardindex<MAXIMUM_NUMBER_OF_EXPANDER_BOARDS; boardindex++) // boardindex: Index auf je 4-Ports (ein IO-Board)
	{
		if (expBoard[boardindex] != 255)
		{
			for (port=0; port<4; port++)
			{
				if (!((expBoard[boardindex] & (1<< port)) != 0)) // als OUTPUT konfiguriert?
				{
					if (n < (expStartPins[portindex]+8))
					{
						n -= expStartPins[portindex]; // auf den Bereich 0-7 holen
						*pportindex = portindex;
						return (port>1) ? (7 - n) : n; // Port B: Pins sind zu spiegeln (0 -> 7, 1 -> 6 etc.)
					}
				}

				portindex++;
			}
		}
		else portindex += 4; // Board nicht konfiguriert
	}

	canix_syslog_P(SYSLOG_PRIO_ERROR, PSTR("Exp:OutPin %d NG"), n);
	return 0; // Output-Pin nicht gefunden
}
Exemplo n.º 7
0
void load_page(uint8_t page)
{
    // ueber alle eds bloecke iterieren und die Seite suchen
    //
    //

    eds_block_p it;

    canix_syslog_P(SYSLOG_PRIO_DEBUG,PSTR("load page %d\n"),page);


    /*
    it = eds_find_next_block_between(EDS_DATA_START,
    		EDS_PAGE_ID_START, EDS_PAGE_ID_END);
    for (; it != 0; it = eds_find_next_block_between(it,
    			EDS_PAGE_ID_START, EDS_PAGE_ID_END))
    			*/

    EDS_foreach_block_between(it, EDS_PAGE_ID_START, EDS_PAGE_ID_END)
    {
        uint8_t page_id;

        // War testweise noetig, um den Bug (siehe /prj/tickets/TID0938/Log)
        // zu fixen:
        // if ((EDS_BLOCK_TYPE(it) < 100) || (EDS_BLOCK_TYPE(it) > 150))
        //	continue;

        page_id = EDS_BLOCK_DATA(it,0);


        if (page_id == page)
        {
            // wir haben die Seite gefunden; jetzt muss sie in
            // die lcdpage_t Struktur kopiert werden
            //
            // Die 2 sind fuer den Header des Blocks; den wollen wir
            // auch laden, um mit dem Typ arbeiten zu koennen
            size_t size = EDS_BLOCK_SIZE(it) + 2;

            if ((size) > sizeof(lcdstate.active_page))
            {
                canix_syslog_P(SYSLOG_PRIO_ERROR,PSTR("page (%d) size too large\n"),page);
                load_error_page(ERROR_PAGE_SIZE_TOO_LARGE);
            }
            else
            {
                canix_syslog_P(SYSLOG_PRIO_DEBUG,PSTR("load_page: #1 .ap.block_type=%d\n"),lcdstate.active_page.block_type);
                canix_syslog_P(SYSLOG_PRIO_DEBUG,PSTR("load_page: #1 .ap.block_size=%d\n"),lcdstate.active_page.block_size);
                canix_syslog_P(SYSLOG_PRIO_DEBUG,PSTR("load_page: #1 .ap.page_id=%d\n"),lcdstate.active_page.page_id);
                eeprom_read_block(&lcdstate.active_page, it, size);
                canix_syslog_P(SYSLOG_PRIO_DEBUG,PSTR("load_page: #2 .ap.block_type=%d\n"),lcdstate.active_page.block_type);
                canix_syslog_P(SYSLOG_PRIO_DEBUG,PSTR("load_page: #2 .ap.block_size=%d\n"),lcdstate.active_page.block_size);
                canix_syslog_P(SYSLOG_PRIO_DEBUG,PSTR("load_page: #2 .ap.page_id=%d\n"),lcdstate.active_page.page_id);
                return;
            }
        }
    }
Exemplo n.º 8
0
/** 
 * Schaltet die HK-Ventile aus, wenn ein Heizstop vorliegt. Dies sollte
 * in regelmaessigen Abstaenden aufgerufen werden, da eventuell aufgrund der
 * Heizsteuerlogik die PWM nicht regelmaessig upgedatet wird und so das HK-Ventil
 * nicht auf den Reedkontakt reagiert.
 */
void heizung_update_heizstop(device_data_heizung *p)
{
	if (p->reed_heiz_stop_counter)
	{
		canix_syslog_P(SYSLOG_PRIO_DEBUG,
				PSTR("Heizstop aktiv (id=%d)"), p->config.id);


		// Heizung ganz ausschalten
		p->pwm_end = p->config.pwm_periode;
		p->pwm_width = 0;
	}
}
Exemplo n.º 9
0
static void calibration(device_data_rolladen *p)
{
	if (p->config.feature & (1<<FEATURE_KALIBRIERUNG_OBEN))
	{
		if (p->soll_laufzeit > p->config.laufzeit)
		{
			// in Oben-Lage kalibrieren:
			p->laufzeit = p->config.laufzeit; // Obenlage erreicht
			canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("co"));

			p->summe_laufzeit = 0; // Erst nach Untenabschaltung die Kalibrierung beenden!
			p->kalibrieren = 0;
		}
	}
	else if (p->soll_laufzeit < -1)
	{
		// in Unten-Lage kalibrieren:
		p->laufzeit = 0; // Untenlage erreicht
		canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("cu"));

		p->summe_laufzeit = 0; // Erst nach Untenabschaltung die Kalibrierung beenden!
		p->kalibrieren = 0;
	}
}
Exemplo n.º 10
0
/** getGroup liefert die Gruppe abh. von lastPotiPos. */
static uint8_t getGroup(device_data_multitaster *p)
{
	uint8_t *gruppen;
	gruppen = (uint8_t *) &(p->config.gruppe0);

	if(p->lastPotiPos < MAX_MULTITASTER_GROUPS)
	{
		return gruppen[p->lastPotiPos]; //gruppe0..X abh vom Potibereich zurueckgeben
	}
	else
	{
		canix_syslog_P(SYSLOG_PRIO_ERROR, PSTR("Err:lastPotiPos="), p->lastPotiPos);
		return 255; //Gruppe 255
	}
}
Exemplo n.º 11
0
uint8_t get_count_lampen_states(void)
{
    // eingeschaltet zaehlen:
    uint8_t n_powerport_on = 0;
    uint8_t i;
    for (i = 0; i < 24; i++)
    {
        if (monitor_lampen_state[i] && (monitor_lampen_state[i] != 255))
        {
            n_powerport_on++;
            canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("L%d"), i);
        }
    }

    //canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("c%d"), n_powerport_on);
    return n_powerport_on;
}
Exemplo n.º 12
0
void canix_unreg_idle_callback(canix_idle_callback callback)
{
	uint8_t i;

	for (i = 0; i < MAX_IDLE_CALLBACKS; i++)
	{
		if (idle_callback[i] == callback)
		{
			idle_callback[i] = 0; // unregister
			return;
		}
	}

#ifdef CANIX_SYSLOG
	canix_syslog_P(SYSLOG_PRIO_CRITICAL, PSTR("idle: handler not registered"));
#endif
}
Exemplo n.º 13
0
void canix_reg_rtc_callback(canix_rtc_callback callback)
{
	uint8_t i;

	for (i = 0; i < MAX_RTC_CALLBACKS; i++)
	{
		if (rtc_callback[i] == 0)
		{
			rtc_callback[i] = callback;
			return;
		}
	}

#ifdef CANIX_SYSLOG
	canix_syslog_P(SYSLOG_PRIO_CRITICAL, PSTR("rtc: no more handlers"));
#endif
}
Exemplo n.º 14
0
void heizung_init(device_data_heizung *p, eds_block_p it)
{
	p->it = it;
	p->mode = HEIZUNG_MODE_OFF;
	p->manual_rate = 0;
	p->pwm_counter = 0;
	p->pwm_width = 0;
	p->pwm_end = 0;
	p->waermebedarf_counter = p->config.id & 0x3f; // Pseudo-Zufall Init
	p->received_interval_counter = 255;
	p->measure_value = 0;
	p->duration_counter = 0;
	p->thermostat_temp = 0;
	p->reed_heiz_stop_counter = 0;
	p->ventilpflege_counter = 0;
	canix_syslog_P(SYSLOG_PRIO_DEBUG,
			PSTR("heizung_init: %d"), p->config.id);
}
Exemplo n.º 15
0
void canix_reg_frame_callback(canix_frame_callback callback, 
		int dst, uint8_t proto, uint8_t srv)
{
	uint8_t i;

	for (i = 0; i < MAX_FRAME_CALLBACKS; i++)
	{
		if (frame_callback_entry[i].callback == 0)
		{
			frame_callback_entry[i].callback = callback;
			frame_callback_entry[i].dst      = dst;
			frame_callback_entry[i].proto    = proto;
			frame_callback_entry[i].srv      = srv;
			return;
		}
	}

#ifdef CANIX_SYSLOG
	canix_syslog_P(SYSLOG_PRIO_CRITICAL, PSTR("reg_frame: no more handlers"));
#endif
}
Exemplo n.º 16
0
/** setADMUX stellt den uC-internen Multiplexer entsprechend der Port-
 *  Konfiguration des EDS-Poti-Objekts ein.
 *  Acht ADC-Pins sind an den Ports PA0-PA7 = IN15-IN8 verfuegbar. */
static void setADMUX(uint8_t config_port)
{
	/* Defines for ADC-Mux with int. ref.-voltage:
	 * REFS0=1: internal 2.56V voltage reference */
	switch (config_port)
	{
		case 15 :
			ADMUX = (1<<REFS0) | 0; //ADC0 = 0 = 0b000
			break;
		case 14 :
			ADMUX = (1<<REFS0) | 1; //ADC1 = 1 = 0b001
			break;
		case 13 :
			ADMUX = (1<<REFS0) | 2; //ADC2 = 2 = 0b010
			break;
		case 12 :
			ADMUX = (1<<REFS0) | 3; //ADC3 = 3 = 0b011
			break;
		case 11 :
			ADMUX = (1<<REFS0) | 4; //ADC4 = 4 = 0b100
			break;
		case 10 :
			ADMUX = (1<<REFS0) | 5; //ADC5 = 5 = 0b101
			break;
		case  9 :
			ADMUX = (1<<REFS0) | 6; //ADC6 = 6 = 0b110
			break;
		case  8 :
			ADMUX = (1<<REFS0) | 7; //ADC7 = 7 = 0b111
			break;
		default:
			canix_syslog_P(SYSLOG_PRIO_ERROR,
					PSTR("poti-port=%d. Richtig waere IN8 bis IN15."),
					config_port);
			break;
	}
}
Exemplo n.º 17
0
void heizung_check_ventilpflege(device_data_heizung *p)
{
	// Pruefen: ist die Heizung aus und keine Ventilpflege aktiv? 
	// Nur dann pruefen wir weiter, ob eine Ventilpflege ansteht:
	if ((p->mode == HEIZUNG_MODE_OFF) && (p->ventilpflege_counter == 0))
	{
		// Startzeitpunkt der Ventilpflege ist immer:
		// Sonntags, 12:00 + Heizungs-ID * 3
		//
		// Beispiel: ID: 67;  -> Startzeitpunkt: 3:21
		// Beispiel: ID: 160; -> Startzeitpunkt: 8:00

		uint16_t time = canix_rtc_clock.hour * 60 + canix_rtc_clock.minute;

		if ((canix_rtc_clock.day_of_week == 7) && // Sonntag
				(time == (p->config.id * 3) + (12*60 + 0)))
		{
			// Ventilpflege aktivieren:
			p->ventilpflege_counter = 600;
			canix_syslog_P(SYSLOG_PRIO_DEBUG,
					PSTR("heizung %d: ventilpflege"), p->config.id);
		}
	}
}
Exemplo n.º 18
0
void heizung_can_callback(device_data_heizung *p, const canix_frame *frame)
{
	canix_frame answer;

	answer.src = canix_selfaddr();
	answer.dst = frame->src;
	answer.proto = HCAN_PROTO_SFP;
	answer.data[0] = HCAN_SRV_HES;

	switch (frame->data[1])
	{
		case HCAN_HES_1WIRE_TEMPERATURE :
			if (frame->data[2] == p->config.sensor_id)
			{
				// we have a heizung and a temp sensor frame
				// now look if if fits to the heizung

				// temperature is a fixed point number mit 4 LSB Bits
				int16_t sensor_temp = frame->data[3] << 8 | 
					frame->data[4];

				// store the measure value
				p->measure_value = sensor_temp;
				p->received_interval_counter = 0;
			}
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_OFF :
			if (p->config.id == frame->data[2])
				p->mode = HEIZUNG_MODE_OFF;
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_MANUAL :
			if (p->config.id == frame->data[2])
			{
				p->mode = HEIZUNG_MODE_MANUAL;
				p->manual_rate = frame->data[3];
				p->duration_counter = (frame->data[4] << 8) | frame->data[5];
			}
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_THERMOSTAT_DETAILS :
			if (p->config.id == frame->data[2])
			{
				p->mode = HEIZUNG_MODE_THERMOSTAT;
				p->thermostat_temp = (frame->data[3] << 8) | frame->data[4];
				p->duration_counter = (frame->data[5] << 8) | frame->data[6];
			}
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_AUTOMATIK:
			if (p->config.id == frame->data[2])
				p->mode = HEIZUNG_MODE_AUTOMATIK;
			break;

		case HCAN_HES_HEIZUNG_DETAILS_REQUEST :
			{
				if (p->config.id == frame->data[2])
				{
					switch (p->mode)
					{
						case HEIZUNG_MODE_OFF :
							answer.data[1] = 
								HCAN_HES_HEIZUNG_MODE_OFF_DETAILS;
							answer.data[2] = p->config.id;
							answer.size = 3;
							canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
							break;

						case HEIZUNG_MODE_MANUAL :
							answer.data[1] = 
								HCAN_HES_HEIZUNG_MODE_MANUAL_DETAILS;
							answer.data[2] = p->config.id;
							answer.data[3] = p->manual_rate;
							answer.data[4] = p->duration_counter >> 8;
							answer.data[5] = p->duration_counter;
							answer.size = 6;
							canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
							break;

						case HEIZUNG_MODE_THERMOSTAT :
							answer.data[1] = 
								HCAN_HES_HEIZUNG_MODE_THERMOSTAT_DETAILS;
							answer.data[2] = p->config.id;
							answer.data[3] = p->thermostat_temp >> 8;
							answer.data[4] = p->thermostat_temp;
							answer.data[5] = p->duration_counter >> 8;
							answer.data[6] = p->duration_counter;
							answer.size = 7;
							canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
							break;

						case HEIZUNG_MODE_AUTOMATIK :
							{
								int8_t index;
								index = heizung_get_matching_zeitzone_index(p);
								if (index != -1)
								{
									// we got an zeitzone which matches
									int16_t master_value = 0;
									solltemp_line_t *zeitzone = 
										(solltemp_line_t *) 
										&(p->config.zeitzone0_id);

									master_value = zeitzone[index].temp;
									answer.data[1] = 
										HCAN_HES_HEIZUNG_MODE_AUTOMATIK_DETAILS;
									answer.data[2] = frame->data[2];
									answer.data[3] = master_value >> 8;
									answer.data[4] = master_value;
									answer.data[5] = 
										heizung_get_matching_zeitzone_id(p);
									answer.size = 6;
								}
								else
								{
									canix_syslog_P(SYSLOG_PRIO_ERROR,
											PSTR("zeitzone: no match!"));

									answer.data[1] = 
										HCAN_HES_HEIZUNG_MODE_AUTOMATIK_DETAILS;
									answer.data[2] = frame->data[2];
									answer.data[3] = 0;
									answer.data[4] = 0;
									answer.data[5] = 0;
									answer.size = 6;
								}
								canix_frame_send_with_prio(&answer, 
										HCAN_PRIO_HI);
							}
							break;
					}
				}
			}
Exemplo n.º 19
0
void rolladen_can_callback(device_data_rolladen *p, const canix_frame *frame)
{
	canix_frame answer;

	answer.src = canix_selfaddr();
	answer.dst = frame->src;
	answer.proto = HCAN_PROTO_SFP;
	answer.data[0] = HCAN_SRV_HES;

	switch (frame->data[1])
	{
		case HCAN_HES_ROLLADEN_POSITION_SET:
			if (is_group_in_rolladen(p, frame->data[2]))
			{
				switch (frame->data[3])
				{
					case 200: // Taster-Down im 2-Taster-Betrieb: ZU = 0 %
						if (p->mute || p->blockingTimer) return; // Befehl abblocken

						if (p->power || p->soll_power)
							rolladen_cmd_stop (p); // anhalten, falls der Rolladen faehrt
						else if (set_soll_laufzeit(p, ROLLADEN_DIR_AB))
						{
							// noch nicht in soll-Position:
							p->long_pressed_counter = 10; // 1 s
							rolladen_cmd_drive (p);
						}
						break;

					case 201: // Taster-Down im 2-Taster-Betrieb: AUF = 100 %
						if (p->mute || p->blockingTimer) return; // Befehl abblocken

						if (p->power || p->soll_power)
							rolladen_cmd_stop (p); // anhalten, falls der Rolladen faehrt
						else if (set_soll_laufzeit(p, ROLLADEN_DIR_AUF)) // noch nicht in soll-Position?
						{
							// noch nicht in soll-Position:
							p->long_pressed_counter = 10; // 1 s
							rolladen_cmd_drive (p);
						}
						break;

					case 202: // HALT ueber Web-Interface
						p->long_pressed_counter = -1; // abmelden (2-Taster-Betrieb)
						rolladen_cmd_stop (p);
						break;

					case 222: // Taster-Up im 2-Taster-Betrieb
						p->long_pressed_counter = -1; // abmelden
						break;

					default: // frame->data[3] = Positionsvorgabe in %
						if (p->mute || p->blockingTimer) return; // Befehl abblocken

						p->soll_laufzeit = (int32_t)p->config.laufzeit * frame->data[3] / 100;
						canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("s %d"), p->soll_laufzeit);
						if (p->soll_laufzeit < 0) p->soll_laufzeit = 0;
						if (p->soll_laufzeit > p->config.laufzeit) p->soll_laufzeit = p->config.laufzeit;

						if (p->power || p->soll_power || p->soll_laufzeit == p->laufzeit)
						{
							p->soll_laufzeit = -1;
							return; // ignorieren, falls der Rolladen faehrt  oder  die Soll-Pos. schon hat
						}

						p->kalibrieren = 0; // nicht kalibrieren
						if (p->soll_laufzeit < p->laufzeit)	p->soll_dir = ROLLADEN_DIR_AB;
						else p->soll_dir = ROLLADEN_DIR_AUF;
						rolladen_cmd_drive (p);
				}
			}
			break;

		case HCAN_HES_TASTER_DOWN: // Nur im 1-Taster-Betrieb verwendet
			if (is_group_in_rolladen(p, frame->data[2]))
			{
				if (p->mute || p->blockingTimer) return; // Befehl abblocken

				if (p->power)
				{
					p->change_dir_counter = 7; // 0,7 s (1-Taster-Betrieb: Richtungswechsel, falls lange gedrueckt)
					rolladen_cmd_stop (p); // anhalten, falls der Rolladen faehrt
				}
				else
				{
					set_soll_laufzeit(p, p->last_dir);
					if (p->soll_laufzeit != -1) // liegt soll-Position bereits vor?
						rolladen_cmd_drive (p);
				}
			}
			break;

		case HCAN_HES_TASTER_UP: // Nur im 1-Taster-Betrieb verwendet
			if (is_group_in_rolladen(p, frame->data[2]))
				p->change_dir_counter = -1; // abmelden (1-Taster-Betrieb)
			break;

		case HCAN_HES_ROLLADEN_DEFINE_POSITION:
			{
				// Da die Rolladen keine Rueckmeldung geben, wo sie
				// gerade stehen, kann im Service-Falle (z.B. bei einem
				// Firmware Upgrade die Position der Rollaeden vorher
				// mit HCAN_HES_ROLLADEN_POSITION_REQUEST erfragt und
				// nach dem Upgrade mit HCAN_HES_ROLLADEN_DEFINE_POSITION
				// definiert werden.

				if (is_group_in_rolladen(p, frame->data[2]))
				{
					// Rolladenposition setzen: (pos+1) wegen Rundungsfehler
					p->laufzeit = (int32_t)(frame->data[3]+1) * p->config.laufzeit / 100;

					if (p->laufzeit > p->config.laufzeit) p->laufzeit = p->config.laufzeit;
				}
			}
			break;

		case HCAN_HES_ROLLADEN_POSITION_REQUEST:
			if (is_group_in_rolladen(p, frame->data[2]))
			{
				answer.data[1] = HCAN_HES_ROLLADEN_POSITION_REPLAY;
				answer.data[2] = frame->data[2];
				answer.data[3] = rolladen_get_position(p);
				answer.size = 4;
				canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
			}
			break;
	}

	if (p->config.mute == frame->data[2])
	{
		if (HCAN_HES_MUTE_OFF == frame->data[1])
			p->mute = 0; // Rolladen aktiv
		else if (HCAN_HES_MUTE_ON == frame->data[1])
			p->mute = 1; // Rolladen passiv (per Taster nicht verfahrbar)
	}
}
Exemplo n.º 20
0
/**
 * this timer handler is called every second
 */
void heizung_timer_handler(device_data_heizung *p)
{
	if (p->ventilpflege_counter > 0)
		p->ventilpflege_counter--;

	// Ventilpflege aktivieren, falls der richtige Zeitpunkt dazu ist:
	heizung_check_ventilpflege(p);

	if (p->received_interval_counter != 0xff)
		p->received_interval_counter++;

	heizung_handle_pwm(p);

	if (p->duration_counter > 0)
	{
		p->duration_counter -= 1;
		if (p->duration_counter == 0)
		{
			// Zeit ist abgelaufen; nun wieder auf Automatik-Modus
			// stellen:
			//
			p->mode = HEIZUNG_MODE_AUTOMATIK;
		}
	}

	if (p->reed_heiz_stop_counter > 0)
	{	
		p->reed_heiz_stop_counter -= 1;

		if (p->reed_heiz_stop_counter == 0)
		{
			canix_syslog_P(SYSLOG_PRIO_DEBUG,
					PSTR("heiz-stop ende (heizung %d)"), p->config.id);
		}
	}

	/*
	 * Schaltet die HK-Ventile aus, wenn ein Heizstop vorliegt. Dies passiert
	 * in regelmaessigen Abstaenden, da eventuell aufgrund der Heizsteuerlogik
	 * die PWM nicht regelmaessig upgedatet wird und so das HK-Ventil nicht auf
	 * den Reedkontakt reagiert.
	 */
	heizung_update_heizstop(p);

	if (p->timer_counter++ >= 5)
	{
		p->timer_counter = 0;

		switch (p->mode)
		{
			case HEIZUNG_MODE_OFF : 
				{
					if (p->ventilpflege_counter)
					{
						// Sonderfall: Ventilpflege ist aktiv; dazu
						// Ventil einschalten, sonst aber nichts
						// unternehmen:
						
						p->manual_rate = 0;

						// Ventil einschalten:
						heizung_set_pwm(p,100);
						darlingtonoutput_setpin(p->config.port, 1);

						canix_syslog_P(SYSLOG_PRIO_DEBUG, 
								PSTR("ventilpflege: 1"));
					}
					else
					{
						// das ist Normalfall: keine Ventilpflege aktiv.
						p->manual_rate = 0;
						heizung_set_pwm(p,0);

						// Ventil ausschalten, falls es an ist:
						if (darlingtonoutput_getpin(p->config.port))
							darlingtonoutput_setpin(p->config.port, 0);
					}
					return;
				}
			case HEIZUNG_MODE_MANUAL :
				{
					heizung_set_pwm(p, p->manual_rate);
				}
				break;
			case HEIZUNG_MODE_AUTOMATIK :
				{
					// Wenn ein gueltiger Messwert vorliegt
					// (d.h. wenn innerhalb eines definierten Zeitraumes
					// ein Sensor-Messwert eingetroffen ist:
					if (p->received_interval_counter < 255)
					{
						int8_t index;
						index = heizung_get_matching_zeitzone_index(p);
						if (index != -1)
						{
							// we got an zeitzone which matches
							solltemp_line_t *solltemp_line = (solltemp_line_t*) 
								&(p->config.zeitzone0_id);
							heizung_set_pwm_by_temp(p, 
									solltemp_line[index].temp,
									p->measure_value);
						}
						else
						{
							// keine passende Zeitzone gefunden
							heizung_set_pwm(p,0);
						}
					}
					else
					{
						canix_syslog_P(SYSLOG_PRIO_ERROR, 
								PSTR("keine Sensor-Messwerte vorhanden!"));
					}
				}
				break;
			case HEIZUNG_MODE_THERMOSTAT :
				{
					// Wenn ein gueltiger Messwert vorliegt
					// (d.h. wenn innerhalb eines definierten Zeitraumes
					// ein Sensor-Messwert eingetroffen ist:
					if (p->received_interval_counter < 255)
					{
						heizung_set_pwm_by_temp(p, p->thermostat_temp,
								p->measure_value);
					}
					else
					{
						canix_syslog_P(SYSLOG_PRIO_ERROR, 
								PSTR("keine Sensor-Messwerte vorhanden!"));
					}
				}
				break;
		}
	}

	// Waermebedarfsmeldung versenden:
	if (p->waermebedarf_counter-- == 0)
	{
		canix_frame message;

		// Waermebedarfsmeldungen alle 60 Sekunden
		p->waermebedarf_counter = 60;

		// den aktuellen Ventilstand / Heizrate ermitteln:
		uint8_t rate = heizung_get_pwm(p);

		// Feature-Bit testen, und ggfls Waermebedarf verdoppeln:
		if (p->config.feature & (1<<HEIZUNG_FEATURE_DOPPEL_WAERMEBEDARF))
			rate = rate << 1;

		// Der Waermebedarf ist proportional zur Ventilstellung, d.h.
		// der Bedarf ist hoch, wenn das Ventil voll offen ist, und ist
		// nicht vorhanden, wenn das Ventil zu ist.

		message.src = canix_selfaddr();
		message.dst = HCAN_MULTICAST_INFO;
		message.proto = HCAN_PROTO_SFP;
		message.data[0] = HCAN_SRV_HES;
		message.data[1] = HCAN_HES_HEIZUNG_WAERMEBEDARF_INFO;
		message.data[2] = p->config.id;
		message.data[3] = rate;
		message.size = 4;

		canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);
	}
}
Exemplo n.º 21
0
void lcdctrl_set_display_light(uint8_t mode)
{
	// mode: 0 = inaktiv (Nacht), 1 = aktiv
	if (mode == LCD_MODE_ACTIVE)
	{
		// mode: aktiv (Display leuchtet hell)
		lcdctrl_set_backlight(LCD_BACKLIGHT_DEFAULT);
		lcdctrl_set_contrast(LCD_CONTRAST_DEFAULT);
	}
	else if (mode == LCD_MODE_INACTIVE)
	{
		// mode: inaktiv (Display leuchtet nur zur Orientierung)
		// 
		// Wenn ein EDS Block lcd_light_settings existiert, so muessen
		// die Werte aus diesem ausgelesen werden:

		eds_block_p it, it2;

		canix_syslog_P(SYSLOG_PRIO_DEBUG,
			PSTR("lcdctrl_set_light: mode=inactive"));

		for (it = EDS_DATA_START; it != 0; 
				it = eds_find_next_block(it, EDS_lcd_light_settings_BLOCK_ID))
		{
			// aha, wir haben das passenden Block gefunden
			// Als naechstes muessen die Zeitzonen geprueft werden;
			// Die Werte der ersten Zeitzone, die passt, werden
			// verwendet.
			//
			eds_lcd_light_settings_block_t light_block;

			if (EDS_BLOCK_TYPE(it) != EDS_lcd_light_settings_BLOCK_ID)
				continue;

			eeprom_read_block(&light_block, (it+2), sizeof(light_block));

			canix_syslog_P(SYSLOG_PRIO_DEBUG,
				PSTR("lcdctrl_set_light: light block found @%d"),it);
			canix_syslog_P(SYSLOG_PRIO_DEBUG,
				PSTR(" zeitzone: %d"), light_block.zeitzone_id);
			canix_syslog_P(SYSLOG_PRIO_DEBUG,
				PSTR(" backlight: %d"), light_block.backlight);
			canix_syslog_P(SYSLOG_PRIO_DEBUG,
				PSTR(" contrast: %d"), light_block.contrast);

			// ueber alle Zeitzonen iterieren
			//if (time_matches(p->
			for (it2 = EDS_DATA_START; it2 != 0; 
					it2 = eds_find_next_block(it2, EDS_zeitzone_BLOCK_ID))
			{
				eds_zeitzone_block_t zz;

				if (EDS_BLOCK_TYPE(it2) != EDS_zeitzone_BLOCK_ID)
					continue;

				eeprom_read_block(&zz, (it2+2), sizeof(zz));

				canix_syslog_P(SYSLOG_PRIO_DEBUG,
					PSTR("lcdctrl_set_light: zeit zone found @%d"),it2);

				if ((light_block.zeitzone_id == zz.gruppe) && 
						time_matches (zz.from_hour, zz.from_minute,
							zz.to_hour, zz.to_minute,
							zz.day_pattern))
				{
					// wir haben die gesuchte Zeitzone gefunden und
					// die aktuelle Uhrzeit passt; also 
					
					lcdctrl_set_backlight(light_block.backlight);
					lcdctrl_set_contrast(light_block.contrast);

					canix_syslog_P(SYSLOG_PRIO_DEBUG,
							PSTR("lcdctrl_set_light: %d,%d"),
							light_block.backlight, light_block.contrast);

					return;
				}
			}
		}

		// wenn wir hier angekommen sind, wurde kein passender EDS Block
		// gefunden. In diesem Fall werden die Std-Werte verwendet:

		lcdctrl_set_backlight(LCD_BACKLIGHT_DEFAULT_LOW);
		lcdctrl_set_contrast(LCD_CONTRAST_DEFAULT_LOW);
	}
}
Exemplo n.º 22
0
void idle_handler(void)
{
	uint8_t i;
	uint16_t unusedSRAM; //in bytes

	// 10msec Takt:
	if (timer_event_100th)
	{
		// Event Flag zuruecksetzen
		timer_event_100th = 0;

		for (i = 0; i < MAX_PDEVICE_DATA; i++)
		{
			uint8_t *p = pdevice_data[i];
			if (p)
			{
				switch (*p)
				{
					case EDS_multitaster_BLOCK_ID:
						multitaster_timer_handler ( (device_data_multitaster*) p);
						break;
					case EDS_taster_BLOCK_ID: 
						taster_timer_handler ( (device_data_taster*) p); 
						break;
				}
			}
		}
	}

	// 100msec Takt
	if (timer_event_10th)
	{
		// Event Flag zuruecksetzen
		timer_event_10th = 0;

		for (i = 0; i < MAX_PDEVICE_DATA; i++)
		{
			uint8_t *p = pdevice_data[i];
			if (p)
			{
				switch (*p)
				{
					case EDS_multitaster_BLOCK_ID:
						multitaster_timer_handler ( (device_data_multitaster*) p);
						break;
					case EDS_poti_BLOCK_ID:
						poti_timer_handler ( (device_data_poti*) p);
						break;
					case EDS_rolladen_BLOCK_ID: 
						rolladen_timer_handler ( (device_data_rolladen*) p); 
						break;
					case EDS_rolladenSchlitzpos_BLOCK_ID:
						rolladenSchlitzpos_timer_handler ( (device_data_rolladenSchlitzpos*) p);
						break;
					case EDS_schalter_BLOCK_ID:
						schalter_timer_handler ( (device_data_schalter*) p);
						break;
				}
			}
		}
	}

	// 1sec Takt
	if (timer_event_1)
	{
		// Event Flag zuruecksetzen
		timer_event_1 = 0;

		for (i = 0; i < MAX_PDEVICE_DATA; i++)
		{
			uint8_t *p = pdevice_data[i];
			if (p)
			{
				switch (*p)
				{
					case EDS_dunstabzugport_BLOCK_ID: 
						dunstabzugport_timer_handler ( (device_data_dunstabzugport*) p); 
						break;
					case EDS_helligkeitssensor_BLOCK_ID:
						helligkeitssensor_timer_handler ( (device_data_helligkeitssensor*) p);
						break;
					case EDS_heizung_BLOCK_ID: 
						heizung_timer_handler ( (device_data_heizung*) p); 
						break;
					case EDS_lichtzone_BLOCK_ID: 
						lichtzone_timer_handler ( (device_data_lichtzone*) p); 
						break;
					case EDS_reedkontakt_BLOCK_ID: 
						reedkontakt_timer_handler ( (device_data_reedkontakt*) p); 
						break;
					case EDS_rolladenAutomat_BLOCK_ID:
						rolladenAutomat_timer_handler ( (device_data_rolladenAutomat*) p);
						break;
					case EDS_tempsensor_BLOCK_ID: 
						tempsensor_timer_handler ( (device_data_tempsensor*) p); 
						break;
					case EDS_timeservice_BLOCK_ID: 
						timeservice_timer_handler ( (device_data_timeservice*) p); 
						break;
					case EDS_zeitschaltuhr_BLOCK_ID: 
						zeitschaltuhr_timer_handler ( (device_data_zeitschaltuhr*) p); 
						break;
					case EDS_powerport_BLOCK_ID :
						powerport_timer_handler( (device_data_powerport*) p);
						break;
				}
			}
		}

		unusedSRAM = get_mem_unused();
		if( unusedSRAM < MAX_MEM_CRITICAL_SIZE )
		{
			canix_syslog_P(SYSLOG_PRIO_CRITICAL,
					PSTR("mem_free: %d bytes"), unusedSRAM);
		}
	}

	shiftOut_timer_handler(); //die Ausgaben nachtriggern (Störungsunterdrückung)
}