// 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; } } }
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 }
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; } } }
/* 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 (); }
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; } }
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 }
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; } } }
/** * 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; } }
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; } }
/** 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 } }
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; }
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 }
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 }
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); }
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 }
/** 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; } }
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); } } }
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; } } }
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) } }
/** * 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); } }
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); } }
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) }