Beispiel #1
0
/*!
 *******************************************************************************
 * main program
 ******************************************************************************/
int main(void)
{
    bool last_state_mnt;        //!< motor mounted
    bool state_mnt;             //!< motor mounted
    bool err;                   //!< error
    bool ref_pos_changed;       //!< ref Position changed

    uint8_t last_statekey;      //!< state of keys on last loop
    uint8_t last_second;        //!< RTC-second of last main cycle
    uint8_t ref_position;       //!< desired position in percent
    motor_speed_t speed;        //!< motor speed (fast or quiet)
    uint8_t display_mode;       //!< desired display output
    uint16_t value16;           //!< 16 Bit value
    int16_t value16s;           //!< signed 16 Bit value
    uint8_t value8;             //!<  8 Bit value

    //! initalization
    init();

    //! load/set default values
    load_defauls();
    
    //! Enable interrupts
    sei();

    //! show POST Screen
    LCD_AllSegments(LCD_MODE_ON);                   // all segments on
    delay(1000);
    LCD_AllSegments(LCD_MODE_OFF);        
    LCD_PrintDec(REVHIGH, 1, LCD_MODE_ON);          // print version
    LCD_PrintDec(REVLOW, 0, LCD_MODE_ON);
    LCD_Update();
    delay(1000);
    LCD_AllSegments(LCD_MODE_OFF);                  // all off

    //! \todo Send Wakeup MSG

    state_mnt=false;
    ref_pos_changed=true;
    last_second=99;
    speed=full;
    last_statekey = 0;
    last_state_mnt = false;
    m_key_action = true;
    ref_position = 10;
    display_mode=3;

    ISR(PCINT1_vect);                  // get keystate

		// We should do the following once here to have valid data from the start
    ADC_Measure_Ub();
		ADC_Measure_Temp();

		
    /*!
    ****************************************************************************
    * main loop
    *
    * 1) process keypresses
    *    - m_state_keys and m_wheel are set from IRQ, only process them
    *    - you can set m_wheel to a new value
    *    - controll content of LCD
    * 2) \todo calc new valveposition if new temp available
    *    - temp is measured by IRQ
    * 3) calibrate motor
    *    - start calibration is valve mounted changed to on
    *      (during calibration the main loop stops at least for 10 seconds)
    *    - reset calibration is valve mounted changed to off
    * 4) start motor if
    *    - actual valveposition != desired valveposition && motor is off
    * 5) if motor is on call MOTOR_CheckBlocked at least once a second
    *    - that switches motor of if it is blocked
    * 6) store keystate at end of loop before going to sleep
    * 7) Check for serial command to process
    * 8) \todo goto sleep if
    *    - motor is of
    *    - no key is pressed (AUTO, C, PROG)
    *    - no serial communication active
    ***************************************************************************/
    for (;;){        // change displaystate every 10 seconds 0 to 5
        // Activate Auto Mode
        // setautomode(true);

        // 1) process keypresses
        if (m_key_action){
            m_key_action = false;
            state_mnt = !(m_state_keys & KEYMASK_MOUNT);

            // State of keys AUTO, C and PROG and valve mounted
            if ((m_state_keys & KEYMASK_AUTO) != 0){
                display_mode--;
                LCD_SetHourBarVal(display_mode, LCD_MODE_ON);
                ref_pos_changed = true;
                LCD_SetSeg(LCD_SEG_AUTO, LCD_MODE_ON);
            } else {
                LCD_SetSeg(LCD_SEG_AUTO, LCD_MODE_OFF);
            }
            if ((m_state_keys & KEYMASK_C) != 0){
                if (display_mode==9){
                      m_reftemp = input_temp(m_reftemp);                      
                }                 
                //LCD_SetHourBarVal(display_mode, LCD_MODE_ON);                
                //ref_pos_changed = true;
                //LCD_SetSeg(LCD_SEG_MANU, LCD_MODE_ON);
            } else {
                LCD_SetSeg(LCD_SEG_MANU, LCD_MODE_OFF);
            }
            if ((m_state_keys & KEYMASK_PROG)!= 0){
                display_mode++;
                LCD_SetHourBarVal(display_mode+1, LCD_MODE_ON);
                ref_pos_changed = true;
                LCD_SetSeg(LCD_SEG_PROG, LCD_MODE_ON);
            } else {
                LCD_SetSeg(LCD_SEG_PROG, LCD_MODE_OFF);
            }
        }

        // 2) calc new valveposition if new temp available
        //    - temp is measured by IRQ


        // 3) calibrate motor
        //    - start calibration if valve is now mounted
        //      TODO:
        //      (during calibration the main loop stops for a long time
        //       maybe add global var to cancel callibration, e.g.: if
        //       HR20 removed from ther gear)
        //    - reset calibration is valve mounted changed to off
        if (last_state_mnt != state_mnt) {
            MOTOR_SetMountStatus(state_mnt);
            if (state_mnt) {
                LCD_ClearNumbers();
                LCD_PrintChar(LCD_CHAR_C, 3, LCD_MODE_ON);
                LCD_PrintChar(LCD_CHAR_A, 2, LCD_MODE_ON);
                LCD_PrintChar(LCD_CHAR_L, 1, LCD_MODE_ON);
                LCD_Update();
                // DEBUG: if next line is disabled, not calibration and no
                //        motor control is done
                // MOTOR_Calibrate(ref_position, speed);
                LCD_ClearNumbers();
            } 
        }

        // 4) start motor if
        //    - actual valveposition != desired valveposition
        //    - motor is off
        //    - motor is calibrated
        if ((ref_pos_changed) && (MOTOR_IsCalibrated())){
            err = MOTOR_Goto(ref_position, speed);
            ref_pos_changed = false;
        }

        // 5) if motor is on call MOTOR_CheckBlocked at least once a second
        //    - that switches motor of if it is blocked
        if (MOTOR_On()){
            if (last_second != RTC_GetSecond()){
                MOTOR_CheckBlocked();
                last_second = RTC_GetSecond();
            }
        }
        
        
        // 6) store keystate at end of loop before going to sleep
        last_statekey = m_state_keys;
        last_state_mnt = state_mnt;
	
        
        // 7) Check if there is a serial command to process
        //    Loop until all is processed
				e_meassure();	// test call to sample values and send them to serial port
	
        while( (COM_Process() == true) ){};

        // 8) goto sleep if
        //    - motor is of
        //    - no key is pressed (AUTO, C, PROG)
        //    - no serial communication active
                
        
        if (display_mode==1) {
            // Ub: ADC Value Hex 
            ADC_Measure_Ub();
            value16 = ADC_Get_Bat_Val();
            LCD_PrintHexW(value16, LCD_MODE_ON);
        }else if (display_mode==2) {
            // Ub: ADC Value Decimal 
            ADC_Measure_Ub();
            value16 = ADC_Get_Bat_Val();
            LCD_PrintDecW(value16, LCD_MODE_ON);
        }else if (display_mode==3) {
            // Ub: Voltage [mV]
            ADC_Measure_Ub();            
            value16 = ADC_Get_Bat_Voltage();
            LCD_PrintDecW(value16, LCD_MODE_ON);
        }else if (display_mode==4) {
            // Temp: ADC Value Hex
            ADC_Measure_Temp();
            value16 = ADC_Get_Temp_Val();
            LCD_PrintHexW(value16, LCD_MODE_ON);
        }else if (display_mode==5) {
            // Temp: ADC Value Decimal
            ADC_Measure_Temp();
            value16 = ADC_Get_Temp_Val();
            LCD_PrintDecW(value16, LCD_MODE_ON);            
        }else if (display_mode==6) {
            // Temp: Temperature (Degree)
            ADC_Measure_Temp();
            value16s = ADC_Get_Temp_Degree();
            LCD_PrintTempInt(value16s, LCD_MODE_ON);
        }else if (display_mode==7) {
            // - 9,87 °C            
            value16s = -987;
            LCD_PrintTempInt(value16s, LCD_MODE_ON);
        }else if (display_mode==8) {
            // 98,76 °C            
            value16s = 9876;
            LCD_PrintTempInt(value16s, LCD_MODE_ON);
        }else{
            value16 = display_mode;                      
            LCD_PrintDecW(value16, LCD_MODE_ON);
        }           
        /*
        // Bar 24 on if calibrated
        if (MOTOR_IsCalibrated()) {
            LCD_SetSeg(LCD_SEG_BAR24, LCD_MODE_ON);
        } else {
            LCD_SetSeg(LCD_SEG_BAR24, LCD_MODE_OFF);
        }

        // Hour 0 on if state_mnt
        if (state_mnt) {
            LCD_SetSeg(LCD_SEG_B0, LCD_MODE_ON);
        } else {
            LCD_SetSeg(LCD_SEG_B0, LCD_MODE_OFF);
        }
        
        // Hour 1 on if last_state_mnt
        if (last_state_mnt) {
            LCD_SetSeg(LCD_SEG_B1, LCD_MODE_ON);
        } else {
            LCD_SetSeg(LCD_SEG_B1, LCD_MODE_OFF);
        }

        
        if (!MOTOR_IsCalibrated()) {
            LCD_PrintChar(LCD_CHAR_E, 3, LCD_MODE_ON);
            LCD_PrintChar(LCD_CHAR_2, 2, LCD_MODE_ON);
        } else {
            LCD_PrintDec(ref_position,  1, LCD_MODE_ON);
            LCD_PrintDec(MOTOR_GetPosPercent(),  0, LCD_MODE_ON);
        }
        */
        
        // impulses = MOTOR_GetImpulses();

        // update Display each main loop
        LCD_Update();
    } //End Main loop
    return 0;
}
Beispiel #2
0
/*!
 *******************************************************************************
 * main program
 ******************************************************************************/
int main(void)
{
    //! initalization
    init();

	task=0;

    //! Enable interrupts
    sei();
    
    /* check EEPROM layout */
    if (EEPROM_read((uint16_t)&ee_layout)!=EE_LAYOUT) {
        LCD_PrintStringID(LCD_STRING_EEPr,LCD_MODE_ON);
        task_lcd_update();
        for(;;) {;}  //fatal error, stop startup
    }

	COM_init();

	// We should do the following once here to have valid data from the start

		
    /*!
    ****************************************************************************
    * main loop
    ***************************************************************************/
    for (;;){        
		// go to sleep with ADC conversion start
		asm volatile ("cli");
		if (
          ! task &&
          ((ASSR & (_BV(OCR2UB)|_BV(TCN2UB)|_BV(TCR2UB))) == 0) // ATmega169 datasheet chapter 17.8.1
            ) {
  			// nothing to do, go to sleep
            if(timer0_need_clock() || RS_need_clock()) {
			    SMCR = (0<<SM1)|(0<<SM0)|(1<<SE); // Idle mode
            } else {
    			if (sleep_with_ADC) {
    				SMCR = (0<<SM1)|(1<<SM0)|(1<<SE); // ADC noise reduction mode
				} else {
				    SMCR = (1<<SM1)|(1<<SM0)|(1<<SE); // Power-save mode
                }
            }

			if (sleep_with_ADC) {
				sleep_with_ADC=0;
				// start conversions
		        ADCSRA |= (1<<ADSC);
			}

			DEBUG_BEFORE_SLEEP();
			asm volatile ("sei");	//  sequence from ATMEL datasheet chapter 6.8.
			asm volatile ("sleep");
			asm volatile ("nop");
			DEBUG_AFTER_SLEEP(); 
			SMCR = (1<<SM1)|(1<<SM0)|(0<<SE); // Power-save mode
		} else {
			asm volatile ("sei");
		}

        // update LCD task
		if (task & TASK_LCD) {
			task&=~TASK_LCD;
			task_lcd_update();
			continue; // on most case we have only 1 task, iprove time to sleep
		}

		if (task & TASK_ADC) {
			task&=~TASK_ADC;
			if (task_ADC()==0) {
                // ADC is done
                // TODO
            }
			continue; // on most case we have only 1 task, iprove time to sleep
		}
		
        // communication
		if (task & TASK_COM) {
			task&=~TASK_COM;
			COM_commad_parse();
			continue; // on most case we have only 1 task, iprove time to sleep
		}

        // motor stop
        if (task & TASK_MOTOR_STOP) {
            task&=~TASK_MOTOR_STOP;
            MOTOR_timer_stop();
			continue; // on most case we have only 1 task, iprove time to sleep
        }

        // update motor possition
        if (task & TASK_MOTOR_PULSE) {
            task&=~TASK_MOTOR_PULSE;
            MOTOR_updateCalibration(mont_contact_pooling());
            MOTOR_timer_pulse();
			continue; // on most case we have only 1 task, iprove time to sleep
        }

		//! check keyboard and set keyboards events
		if (task & TASK_KB) {
			task&=~TASK_KB;
			task_keyboard();
		}

        if (task & TASK_RTC) {
            task&=~TASK_RTC;
            {
                bool minute = RTC_AddOneSecond();
                valve_wanted = CTL_update(minute,valve_wanted);
                if (minute && (RTC_GetDayOfWeek()==6) && (RTC_GetHour()==10) && (RTC_GetMinute()==0)) {
                    // every sunday 10:00AM
                    // TODO: improve this code!
                    // valve protection / CyCL
                    MOTOR_updateCalibration(0);
                }
            }
            MOTOR_updateCalibration(mont_contact_pooling());
            MOTOR_Goto(valve_wanted);
            task_keyboard_long_press_detect();
            if ((MOTOR_Dir==stop) || (config.allow_ADC_during_motor)) start_task_ADC();
            if (menu_auto_update_timeout>=0) {
                menu_auto_update_timeout--;
            }
            menu_view(false); // TODO: move it, it is wrong place
            LCD_Update(); // TODO: move it, it is wrong place
            // do not use continue here (menu_auto_update_timeout==0)
        }

		// menu state machine
		if (kb_events || (menu_auto_update_timeout==0)) {
           bool update = menu_controller(false);
           if (update) {
               menu_controller(true); // menu updated, call it again
           } 
           menu_view(update); // TODO: move it, it is wrong place
	       LCD_Update(); // TODO: move it, it is wrong place
		}
    } //End Main loop
Beispiel #3
0
/*!
 *******************************************************************************
 * calibrate the motor and drive it to position in percent
 * \ returns
 *    - true if calibration successfull 
 *    - false if not successfull possible reasons:
 *      - motor is not stopped after \ref MOTOR_MAX_IMPULSES impulses
 *      - motor has been dismounted
 *
 * \param  percent desired position after calibration 0-100
 *         - 0 : closed
 *         - 100 : open
 *
 * \param speed  motorspeed in percent for PWM
 *
 * \note minimises motor time (save power)
 ******************************************************************************/
bool MOTOR_Calibrate(uint8_t percent, motor_speed_t speed)
{
    uint16_t postmp;
    if (percent > 50) {
        // - close till no movement or more than MOTOR_MAX_IMPULSES
        MOTOR_PosAct = MOTOR_MAX_IMPULSES;
        MOTOR_PosStop = 0;
        MOTOR_Control(close, speed);
        do {
            postmp = MOTOR_PosAct;
            delay(200);
        } while ((MOTOR_Dir != stop) && (postmp != MOTOR_PosAct) &&
                  MOTOR_Mounted); // motor still on, moving and mounted
        // stopped by ISR?, turning too long, not mounted -> error
        if ((MOTOR_Dir == stop) || (MOTOR_Mounted==false)){
            return false;
        }
        // motor is on, but not turning any more -> endposition reached -> stop the motor
        MOTOR_Control(stop, speed);
        // now open till no movement or more than MOTOR_MAX_IMPULSES
        MOTOR_PosAct = 0;
        MOTOR_PosStop = MOTOR_MAX_IMPULSES;
        MOTOR_Control(open, speed);
        do {
            postmp = MOTOR_PosAct;
            delay(200);
        } while ((MOTOR_Dir != stop) && (postmp != MOTOR_PosAct) &&
                  MOTOR_Mounted); // motor still on, moving and mounted
        // stopped by ISR?, turning too long, not mounted -> error
        if ((MOTOR_Dir == stop) || (MOTOR_Mounted==false)){
            return false;
        }
        // motor is on, but not turning any more -> endposition reached -> stop the motor
        MOTOR_Control(stop, speed);
        MOTOR_PosMax = MOTOR_PosAct;
    } else {
        // - open till no movement or more than MOTOR_MAX_IMPULSES
        MOTOR_PosAct = 0;
        MOTOR_PosStop = MOTOR_MAX_IMPULSES;
        MOTOR_Control(open, speed);
        do {
            postmp = MOTOR_PosAct;
            delay(200);
        } while ((MOTOR_Dir != stop) && (postmp != MOTOR_PosAct) &&
                  MOTOR_Mounted); // motor still on, moving and mounted
        // stopped by ISR?, turning too long, not mounted -> error
        if ((MOTOR_Dir == stop) || (MOTOR_Mounted==false)){
            return false;
        }
        // motor is on, but not turning any more -> endposition reached -> stop the motor
        MOTOR_Control(stop, speed);
        // now close till no movement or more than MOTOR_MAX_IMPULSES
        MOTOR_PosAct = MOTOR_MAX_IMPULSES;
        MOTOR_PosStop = 0;
        MOTOR_Control(close, speed);
        do {
            postmp = MOTOR_PosAct;
            delay(200);
        } while ((MOTOR_Dir != stop) && (postmp != MOTOR_PosAct) &&
                  MOTOR_Mounted); // motor still on, moving and mounted
        // stopped by ISR?, turning too long, not mounted -> error
        if ((MOTOR_Dir == stop) || (MOTOR_Mounted==false)){
            return false;
        }
        // motor is on, but not turning any more -> endposition reached -> stop the motor
        MOTOR_Control(stop, speed);
        MOTOR_PosMax = MOTOR_MAX_IMPULSES - MOTOR_PosAct;
        MOTOR_PosAct = 0;
    }
    // now MOTOR_PosMax and MOTOR_PosAct calibated
    // goto desired position
    MOTOR_Goto(percent, speed);
    // Send out notify to com.c
    COM_setNotify(NOTIFY_CALIBRATE);	
    // finished
    return true;
}