void tastdimmer_can_callback(device_data_tastdimmer *p, const canix_frame *frame) { if (tastdimmer_is_in_group(p, frame->data[2])) { switch (frame->data[1]) { case HCAN_HES_TASTER_DOWN : darlingtonoutput_setpin(p->config.port, 1); break; case HCAN_HES_TASTER_UP : darlingtonoutput_setpin(p->config.port, 0); break; } } }
void switch_to_battery(void) { canix_frame message; // Status merken: on_battery = 1; // Relais schalten darlingtonoutput_setpin(7,1); // Timer auf 2 Sekunden setzen, d.h. fruehstens in // 2 Sekunden kann die USV wieder reagieren. Das ist noetig // damit kein "Prellen" oder "Flackern" passiert usv_timer = 200; // LEDs anpassen: led_set(3,0); led_set(6,10); // Busteilnehmer informieren: message.src = canix_selfaddr(); message.dst = HCAN_MULTICAST_INFO; message.proto = HCAN_PROTO_SFP; message.data[0] = HCAN_SRV_USVS; message.data[1] = HCAN_USVS_STATE_INFO; message.data[2] = on_battery; message.size = 3; canix_frame_send(&message); }
void switch_to_netzbetrieb(void) { canix_frame message; // Status merken: on_battery = 0; // Relais schalten darlingtonoutput_setpin(7,0); // Auch hier wieder: ein Prellen verhindern usv_timer = 10; // LEDs anpassen: led_set(3,10); led_set(6,0); // Busteilnehmer informieren: message.src = canix_selfaddr(); message.dst = HCAN_MULTICAST_INFO; message.proto = HCAN_PROTO_SFP; message.data[0] = HCAN_SRV_USVS; message.data[1] = HCAN_USVS_STATE_INFO; message.data[2] = on_battery; message.size = 3; canix_frame_send(&message); }
/** * this one cares about the PWM (pulse width modulation) for * achieving heating rates between off and on */ void heizung_handle_pwm(device_data_heizung *p) { if (++p->pwm_counter >= (p->pwm_end)) { p->pwm_counter = 0; darlingtonoutput_setpin(p->config.port, 1); } if (p->pwm_counter >= p->pwm_width) { darlingtonoutput_setpin(p->config.port, 0); } /* canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("handle_pwm: heiz: %d: %d"), p->config.id, darlingtonoutput_getpin(p->config.port)); */ }
/** * 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); } }
// hier werden die anstehenden Rolladenauftraege jede 10-tel Sekunde verarbeitet/angestossen inline void rolladen_timer_handler(device_data_rolladen *p, uint8_t zyklus) { if (zyklus != 10) return; // 10tel-Sekunden-Zyklus verwendet //// Im 2-Taster-Betrieb manuell die Kalibrierung anstossen: if (p->long_pressed_counter > 0) p->long_pressed_counter--; else if (p->long_pressed_counter == 0) { prepare_calibration (p); // kalibrieren per Taster-"ZU" oder "AUF" p->long_pressed_counter = -1; // abmelden } //// Richtungswechsel im 1-Taster-Betrieb: if (p->change_dir_counter > 0) p->change_dir_counter--; else if (p->change_dir_counter == 0) { p->last_dir = !p->last_dir; // Richtungswechsel p->change_dir_counter = -1; // abmelden } //// Soll-/Endlage-Pruefung und ggf. Abschaltung: if (p->power && p->soll_power) // Rolladen faehrt und hat keinen Halt-Auftrag? { if(ROLLADEN_DIR_AB == p->dir) { p->laufzeit--; // Rolladen faehrt runter if (p->laufzeit <= p->soll_laufzeit) rolladen_cmd_stop (p); // Halt-Auftrag durch das Erreichen der Soll-Lage } else // AUF: { p->laufzeit++; // Rolladen faehrt hoch if (p->laufzeit >= p->soll_laufzeit) rolladen_cmd_stop (p); // Halt-Auftrag durch das Erreichen der Soll-Lage } p->summe_laufzeit++; // fuer die Kalibrierung } //// Relais-Blocking: if (p->blockingTimer) p->blockingTimer--; // Blockierung aktiv else { if (p->soll_power) p->exe_power = 1; // Fahr-Auftrag: Power-Relais darf nun eingeschaltet werden else p->exe_dir = 1; // Halt-Auftrag: Dir-Relais darf nun umgeschaltet werden } //// Relais-Execution: if (p->exe_dir && (p->dir != p->soll_dir)) // Aenderung? { darlingtonoutput_setpin(p->config.port_dir, p->soll_dir); p->dir = p->soll_dir; // Relais nur bei Aenderung ansteuern p->exe_dir = 0; // Default: Relais nicht ansprechen } if (p->exe_power && (p->power != p->soll_power)) // Aenderung? { darlingtonoutput_setpin(p->config.port_power, p->soll_power); p->power = p->soll_power; // Relais nur bei Aenderung ansteuern p->exe_power = 0; // Default: Relais nicht ansprechen } if (p->power) p->stoppuhr++; }