예제 #1
0
void get_adc_vdc_high()
{
	int LoopCtrl;

	Uint32 RunTimeMsec,StartTimeMsec;
	double adc_Vdc_in, adc_Vdc_out;
	
	UNION32 u32data;

	load_sci_tx_mail_box( "Start ADC at Vdc high"); delay_msecs(10);

	gfRunTime=0.0;
	LoopCtrl = 1;
	gMachineState = STATE_READY;

	while(LoopCtrl == 1)
	{
		if( gfRunTime >= 1.0 ) LoopCtrl = 0;

		RunTimeMsec = ulGetTime_mSec( StartTimeMsec);
		if(RunTimeMsec > 1){
			StartTimeMsec = ulGetNow_mSec( );
			adc_Vdc_in = (double)giAdcVdc;
			LPF1(0.002,10.0,adc_Vdc_in, & adc_Vdc_out);
		}
	}

	if( gfRunTime >= 1.0 ){

		code_adc_vdc_high = adc_Vdc_out;
		u32data.dword = code_adc_vdc_high; write_code_2_eeprom(CODE_adc_vdc_high,u32data);
						
		load_sci_tx_mail_box("OK adc_vdc_high Saved");delay_msecs(10);				
	}
}
예제 #2
0
/*************************************************************************************
 * This method calculates the voltage that should be output to the PWM peripheral.
 * It takes the reading from the light sensor, scales it appropriately, calculates
 * the P, I, and D values, converts it to the duty cycle value,  and outputs the
 * value to the PWM params.
 **************************************************************************************/
XStatus calc_PID()
{
    double deriv, integral, error, prev_error = 0;
    double volt_out;
    int duty_out;
    XStatus		Status;					// Xilinx return status

    // stabilize the PWM output (and thus the lamp intensity) at the
    // minimum before starting the test
    Status = PWM_SetParams(&PWMTimerInst, pwm_freq, dc_start);
    if (Status == XST_SUCCESS)
    {
        PWM_Start(&PWMTimerInst);
    }
    else
    {
        return -1;
    }
    //Wait for the LED output to settle before starting
    delay_msecs(1500);

    for (smpl_idx = 1; smpl_idx < NUM_FRQ_SAMPLES; smpl_idx++)
    {
        delay_msecs(100);

        // get count from light sensor and convert to voltage
        sample[smpl_idx] = LIGHTSENSOR_Capture(LIGHTSENSOR_BASEADDR, slope, offset, is_scaled, freq_min_cnt);
        volt_out = (-3.3 / 4095.0) * (sample[smpl_idx]) + 3.3;


        // calculate derivative;
        error = setpoint - volt_out;
        deriv = error - prev_error;

        // calculate integral
        if (error < setpoint/10) integral += error;
        else integral = 0;

        // Control offset is gotten from characterization
        volt_out = offset + (error * prop_gain) + (deriv * deriv_gain) + (integral * integral_gain);
        duty_out = (volt_out)* (MAX_DUTY+1)/VOLT_MAX;

        // establish bounds
        if (duty_out < 1) duty_out = 1;
        if (duty_out > 99)duty_out = 99;

        // activate PWM
        Status = PWM_SetParams(&PWMTimerInst, pwm_freq, duty_out);
        if (Status == XST_SUCCESS)
        {
            PWM_Start(&PWMTimerInst);
        }
    }
    return XST_SUCCESS;
}
예제 #3
0
XStatus calc_bang()
{
    Xfloat32 volt_out;
    XStatus		Status;					// Xilinx return status

    // stabilize the PWM output (and thus the lamp intensity) at the
    // minimum before starting the test
    Status = PWM_SetParams(&PWMTimerInst, pwm_freq, dc_start);
    if (Status == XST_SUCCESS)
    {
        PWM_Start(&PWMTimerInst);
    }
    else
    {
        return -1;
    }

    //Wait for the LED output to settle before starting
    delay_msecs(1500);

    for (smpl_idx = 1; smpl_idx < NUM_FRQ_SAMPLES; smpl_idx++)
    {
        // get count from light sensor and convert to voltage
        sample[smpl_idx] = LIGHTSENSOR_Capture(LIGHTSENSOR_BASEADDR, slope, offset, is_scaled, freq_min_cnt);

        volt_out = (-3.3 / 4095.0) * (sample[smpl_idx]) + 3.3;

        if (volt_out < setpoint)
        {
            Status = PWM_SetParams(&PWMTimerInst, pwm_freq, MAX_DUTY);
            delay_msecs(1);
            if (Status == XST_SUCCESS)
            {
                PWM_Start(&PWMTimerInst);
            }
        }
        else
        {
            Status = PWM_SetParams(&PWMTimerInst, pwm_freq, MIN_DUTY);
            delay_msecs(1);
            if (Status == XST_SUCCESS)
            {
                PWM_Start(&PWMTimerInst);
            }
        }
        delay_msecs(100);
    }
    return XST_SUCCESS;
}
예제 #4
0
파일: button_proc.c 프로젝트: eunwho/b2inv
int GetKey()
{
	int KeySave;

	if((KeySave= GetKeyTemp()) != BTN_NULL )
	{
		delay_msecs(20);
		if( ( KeySave = GetKeyTemp()) != BTN_NULL )
		{	
			while( GetKeyTemp() != BTN_NULL);
		}
		delay_msecs(20);		// off bound proc  
	}
	return KeySave;
}
/*****
 * DoTest_Track() - Perform the Tracking test
 * 
 * This function uses the global "pwm_freq" and "pwm_duty" values to adjust the PWM
 * duty cycle and thus the intensity of the LED.  The function displays
 * the light detector reading as it tracks changes in the
 * LED intensity.  This test runs continuously until a different test is selected.
 * Returns XST_SUCCESS since this test can't fail.  Returns approximate sample interval
 * in the global variable "frq_sample_interval"
 *****/ 
XStatus DoTest_Track(void)
{
	static int		old_pwm_freq = 0;			// old pwm_frequency and duty cycle
	static int		old_pwm_duty = 200;			// these values will force the initial display	
	volatile u16	frq_cnt;					// light detector counts to display
	XStatus			Status;						// Xilinx return status
	unsigned		tss;						// starting timestamp			

	if ((pwm_freq != old_pwm_freq) || (pwm_duty != old_pwm_duty))
	{	
		// set the new PWM parameters - PWM_SetParams stops the timer
		Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
		if (Status == XST_SUCCESS)
		{							
			PWM_Start(&PWMTimerInst);
		}

		tss = timestamp;	
		
		//ECE544 Students:
        //make the light sensor measurement
		frq_cnt = LIGHTSENSOR_Capture(LIGHTSENSOR_BASEADDR, slope, offset, is_scaled);

		delay_msecs(1);
		frq_smple_interval = timestamp - tss;
				
		// update the display and save the frequency and duty
		// cycle for next time
		update_lcd(pwm_duty, frq_cnt);
		old_pwm_freq = pwm_freq;
		old_pwm_duty = pwm_duty;
	}
	return XST_SUCCESS;
}
예제 #6
0
파일: code_proc.c 프로젝트: eunwho/b2inv
int init_eprom_data()
{
	UNION32	data,data2;
	int check;
	int address,cmd,loop_ctrl;
	int return_value;

	data.dword  = 0.0;

	cmd = CMD_READ_DATA;
	address = return_value = 0;
	
	loop_ctrl = 1;

	while(loop_ctrl)
	{
		cmd = CMD_READ_DATA;
		check = get_code_information( address, cmd , & code_inform);

		if( check==0 ){
			if( code_inform.type == TYPE_DOUBLE){ 
				data.dword = code_inform.code_default.doubles;
			}
			else{
				data.word.word0 = code_inform.code_default.ints;
			}

			read_eprom_data(address, & data2 );

			if( data.dword != data2.dword)	write_code_2_eeprom( address,data);

			read_eprom_data(address, & data2 );

			if( data.dword != data2.dword)
			{
				loop_ctrl = 0;
				return_value = -1;
				load_sci_tx_mail_box("Trip : eeprom write" );
				delay_msecs(100);
				break;
			}	 
			code_inform.code_value.doubles = data.dword;
			cmd = CMD_WRITE_RAM;
			check = get_code_information( address,cmd, & code_inform);
			address ++;
		}
		else if( check == -2) address = (address/100)*100 + 100;
		else address ++; 		

		if( address >= CODE_GROUP7_END )
		{
			EepromSaveFlag = 0;
			return 0;
		}
	}
	EepromSaveFlag = 0;
	return return_value;
}
예제 #7
0
void set_PID_vals(row, col)
{

    u32 btnsw;

    NX3_readBtnSw(&btnsw);
    // Set which control measurement we're using
    if (btnsw & msk_BTN_NORTH)
    {
        // increment to the next selection.  If we're at the last enum, set it to the 1st (proportional)
        if (PID_current_sel == OFFSET) PID_current_sel = PROPORTIONAL;
        else PID_current_sel = (Control_t)((int)(PID_current_sel+1));  //casting to allow increment

        // cursor control logic
        if (PID_current_sel == PROPORTIONAL)
        {
            row = 1;
            col = 2;
        }
        else if (PID_current_sel == INTEGRAL)
        {
            row = 1;
            col = 7;
        }
        else if (PID_current_sel == DERIVATIVE)
        {
            row = 1;
            col = 12;
        }
        else if (PID_current_sel == OFFSET)
        {
            row  = 2;
            col  = 13;
        }
    }

    delay_msecs(20);
    //set cursor location and turn on cursor
    LCD_setcursor(row,col);
    LCD_docmd(LCD_DISPLAYONOFF, LCD_CURSOR_ON);


    if (btnsw & msk_BTN_EAST)
    {
        if (PID_current_sel == PROPORTIONAL)     prop_gain     += GAIN_INCREMENT;
        else if (PID_current_sel == INTEGRAL)    integral_gain += GAIN_INCREMENT;
        else if (PID_current_sel == DERIVATIVE)  deriv_gain    += GAIN_INCREMENT;
        else                                     offset        += GAIN_INCREMENT;
    }
    if (btnsw & msk_BTN_WEST)
    {
        if (PID_current_sel == PROPORTIONAL)     prop_gain     -= GAIN_INCREMENT;
        else if (PID_current_sel == INTEGRAL)    integral_gain -= GAIN_INCREMENT;
        else if (PID_current_sel == DERIVATIVE)  deriv_gain    -= GAIN_INCREMENT;
        else                                     offset        -= GAIN_INCREMENT;
    }
}
/*****
 * DoTest_Step() - Perform the Step test
 * 
 * This function stabilizes the duty cycle at "dc_start" for
 * about a second and a half and then steps the duty cycle from min to max or
 * max to min depending on the test. NUM_FRQ_SAMPLES are collected
 * into the global array sample[].  An approximate sample interval
 * is written to the global variable "frq_smpl_interval"
 *****/ 
XStatus DoTest_Step(int dc_start)
{	
	XStatus		Status;					// Xilinx return status
	unsigned	tss;					// starting timestamp
	u16			frq_cnt;				// measured counts to display
		
	// stabilize the PWM output (and thus the lamp intensity) before
	// starting the test
	Status = PWM_SetParams(&PWMTimerInst, pwm_freq, dc_start);
	if (Status == XST_SUCCESS)
	{							
		PWM_Start(&PWMTimerInst);
	}
	else
	{
		return XST_FAILURE;
	}
	//Wait for the LED output to settle before starting
    delay_msecs(1500);
		
	if (dc_start > STEPDC_MAX / 2)
	{
		 Status = PWM_SetParams(&PWMTimerInst, pwm_freq, STEPDC_MIN); 
	}
	else
	{
		 Status = PWM_SetParams(&PWMTimerInst, pwm_freq, STEPDC_MAX); 
	}		
	if (Status == XST_SUCCESS)
	{							
		PWM_Start(&PWMTimerInst);
		pwm_duty = dc_start;
	}
	else
	{
		return XST_FAILURE;
	}
	
	// gather the samples
	smpl_idx = 0;
	tss = timestamp;
	while (smpl_idx < NUM_FRQ_SAMPLES)
	{
	
		//ECE544 Students:
        //make the light sensor measurement
		sample[smpl_idx++] = LIGHTSENSOR_Capture(LIGHTSENSOR_BASEADDR, slope, offset, is_scaled);
		
	}		
	frq_smple_interval = (timestamp - tss) / NUM_FRQ_SAMPLES;
	return XST_SUCCESS;
}
예제 #9
0
void get_adc_offset()
{
	int LoopCtrl;

	Uint32 RunTimeMsec,StartTimeMsec;
	double u_offset_in, v_offset_in;
	double R_offset_in, S_offset_in;

	double u_offset_out, v_offset_out;
	double R_offset_out, S_offset_out;
	
	UNION32 u32data;

	load_sci_tx_mail_box( "\n***********************"); delay_msecs(10);
	load_sci_tx_mail_box( "\n Start ADC Offset Calc "); delay_msecs(10);
	load_sci_tx_mail_box( "\n***********************"); delay_msecs(10);

	gfRunTime=0.0;
	LoopCtrl = 1;

	while(LoopCtrl == 1)
	{
		if( gfRunTime >= 5.0 ) LoopCtrl = 0;
		RunTimeMsec = ulGetTime_mSec( StartTimeMsec);
		if(RunTimeMsec > 1){
			StartTimeMsec = ulGetNow_mSec( );
			u_offset_in = (double)giAdcUphase;
			v_offset_in = (double)giAdcVphase;
			R_offset_in = (double)giAdcRphase;
			S_offset_in = (double)giAdcSphase;

			LPF1(0.002,10.0,u_offset_in, & u_offset_out);
			LPF1(0.002,10.0,v_offset_in, & v_offset_out);
			LPF1(0.002,10.0,R_offset_in, & R_offset_out);
			LPF1(0.002,10.0,S_offset_in, & S_offset_out);
		}
	}

	if( gfRunTime >= 5.0 ){
		adc_u_offset = (int)u_offset_out;
		adc_v_offset = (int)v_offset_out;

		adc_R_offset = (int)R_offset_out;
		adc_S_offset = (int)S_offset_out;

		u32data.word.word0 = adc_u_offset; write_code_2_eeprom(CODE_adc_u_offset,u32data);
		u32data.word.word0 = adc_v_offset; write_code_2_eeprom(CODE_adc_v_offset,u32data);

		u32data.word.word0 = adc_R_offset; write_code_2_eeprom(CODE_adc_R_offset,u32data);
		u32data.word.word0 = adc_S_offset; write_code_2_eeprom(CODE_adc_S_offset,u32data);
				
		load_sci_tx_mail_box("\n*********************");delay_msecs(10);		
		load_sci_tx_mail_box("\n OK Adc offset Saved ");delay_msecs(10);		
		load_sci_tx_mail_box("\n*********************");delay_msecs(10);		
	}
}
예제 #10
0
int main()
{
	XStatus 	Status;
	u32			btnsw, old_btnsw = 0x000000FF;
	int			rotcnt, old_rotcnt = 0x1000;	
	bool		done = false;
	
	// initialize devices and set up interrupts, etc.
 	Status = do_init();
 	if (Status != XST_SUCCESS)
 	{
 		LCD_setcursor(1,0);
 		LCD_wrstring("****** ERROR *******");
 		LCD_setcursor(2,0);
 		LCD_wrstring("INIT FAILED- EXITING");
 		exit(XST_FAILURE);
 	}
 	
	// initialize the global variables
	timestamp = 0;							
	pwm_freq = INITIAL_FREQUENCY;
	pwm_duty = INITIAL_DUTY_CYCLE;
	clkfit = 0;
	new_perduty = false;
    
	// start the PWM timer and kick of the processing by enabling the Microblaze interrupt
	PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);	
	PWM_Start(&PWMTimerInst);
    microblaze_enable_interrupts();
    
	// display the greeting   
    LCD_setcursor(1,0);
    LCD_wrstring(" PWM LIB TEST R0");
	LCD_setcursor(2,0);
	LCD_wrstring(" by Roy Kravitz ");
	NX3_writeleds(0x000000FF);
	delay_msecs(2000);
	NX3_writeleds(0x00000000);
		
   // write the static text to the display
    LCD_clrd();
    LCD_setcursor(1,0);
    LCD_wrstring("G|FR:    DCY:  %");
    LCD_setcursor(2,0);
    LCD_wrstring("Vavg:           ");
      
    // main loop
	do
	{ 
		// check rotary encoder pushbutton to see if it's time to quit
		NX3_readBtnSw(&btnsw);
		if (btnsw & msk_BTN_ROT)
		{
			done = true;
		}
		else
		{
			new_perduty = false;				
			if (btnsw != old_btnsw)
			{	 
				switch (btnsw & PWM_FREQ_MSK)
				{
					case 0x00:	pwm_freq = PWM_FREQ_10HZ;	break;
					case 0x01:	pwm_freq = PWM_FREQ_100HZ;	break;
					case 0x02:	pwm_freq = PWM_FREQ_1KHZ;	break;
					case 0x03:	pwm_freq = PWM_FREQ_10KHZ;	break;
                                        case 0x04: 	pwm_freq = PWM_FREQ_50KHZ;	break;
                                        case 0x05: 	pwm_freq = PWM_FREQ_100KHZ;	break;
                                        case 0x06: 	pwm_freq = PWM_FREQ_150KHZ;	break;
                                        case 0x07: 	pwm_freq = PWM_FREQ_200KHZ;	break;
				}
				old_btnsw = btnsw;
				new_perduty = true;
			}
		
			// read rotary count and handle duty cycle changes
			// limit duty cycle to 0% to 99%
			ROT_readRotcnt(&rotcnt);
			if (rotcnt != old_rotcnt)
			{
				pwm_duty = MAX(0, MIN(rotcnt, 99));
				old_rotcnt = rotcnt;
				new_perduty = true;
			}

			// update generated frequency and duty cycle	
			if (new_perduty)
			{
				u32 freq, dutycycle;
				float vavg;
				char	s[10];
			
				// set the new PWM parameters - PWM_SetParams stops the timer
				Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
				if (Status == XST_SUCCESS)
				{
					PWM_GetParams(&PWMTimerInst, &freq, &dutycycle);
					update_lcd(freq, dutycycle, 1);
					vavg = dutycycle * .01 * 3.3;
					voltstostrng(vavg, s);
					LCD_setcursor(2,5);
					LCD_wrstring(s); 
										
					PWM_Start(&PWMTimerInst);
				}
			}
		}			
	} while (!done);
	
	// wait until rotary encoder button is released		
	do
	{
		NX3_readBtnSw(&btnsw);
		delay_msecs(10);
	} while ((btnsw & msk_BTN_ROT) == 0x80);

	// and say goodbye
	LCD_clrd();
	LCD_wrstring("That's all folks");
	delay_msecs(2000);
	LCD_clrd();
	exit(XST_SUCCESS);
 }
예제 #11
0
파일: scib.c 프로젝트: eunwho/b2inv
// read data format   "9:4:123:x.xxxe-x"
// write data format  "9:6:123:1.234e-3"
void scib_cmd_proc( int * sci_cmd, double * sci_ref)
{
	double data,dbtemp;
	int addr,check,temp;
	char str[30]={0};

	TRIP_INFO * TripData;
	 
	* sci_cmd = CMD_NULL;
	* sci_ref = 0.0;

	if( scib_rx_msg_flag == 0) return;

	scib_rx_msg_flag = 0;

	if ( scib_rx_msg_box[0] != '9') return;
	
	addr =  (scib_rx_msg_box[4]- '0')* 100 +(scib_rx_msg_box[5]- '0')*10 + (scib_rx_msg_box[6]- '0');
	scib_rx_msg_box[16]=0;
	data =  atof( & scib_rx_msg_box[8]);
	
	// regist write function decoding
	
	if( scib_rx_msg_box[2] == '6'){
		if( addr == 900 ){
			check = (int)data;
			if(check == 10){
				* sci_cmd = CMD_START;
				* sci_ref = code_btn_start_ref;
				load_scib_tx_mail_box("UART CMD_START");		
			}
			else if( check == 20 ){
				* sci_cmd = CMD_STOP;  * sci_ref = 0.0;
				load_scib_tx_mail_box("UART CMD_STOP");		
			}
			else if( check == 30 ){
				* sci_cmd = CMD_RESET;  * sci_ref = 0.0;
				load_scib_tx_mail_box("UART CMD_RESET");		
			}
			else if( data == 40 ){
				* sci_cmd = CMD_SAVE;  * sci_ref = 0.0;
				load_scib_tx_mail_box("UART CMD_SAVE");		
			}
			else if( data == 80 ){
				* sci_cmd = CMD_NULL;  * sci_ref = 0.0;
				get_adc_offset();
			}
			else if( data == 90 ){
				* sci_cmd = CMD_NULL;  * sci_ref = 0.0;
				load_scib_tx_mail_box("EEPROM init Start");		
				check = init_eprom_data();		// 0이 아니면 address value
				if( check != 0) load_scib_tx_mail_box("EEPROM init Fail");		
				else		load_scib_tx_mail_box("EEPROM init Success");
			}
			else{
				load_scib_tx_mail_box("Illegal CMD data");		
			}
		}
		else{
			// registor_write_proc(addr,data);
			check = SaveDataProc(addr, data);
			Nop();
		}
	}

//==================
//   read routine
//====================
	else if(scib_rx_msg_box[2] == '4'){
	
		if(addr == 901){	//	monitor state
			check = (int)data;
			if(check == 0){
				switch(gMachineState){
					case STATE_POWER_ON:	load_scib_tx_mail_box("[POWE_ON] "); break;		
					case STATE_READY: 		load_scib_tx_mail_box("[READY]   "); break;		
					case STATE_RUN: 		load_scib_tx_mail_box("[RUN ]    "); break;		
					case STATE_TRIP: 		load_scib_tx_mail_box("[TRIP]    "); break;		
					case STATE_INIT_RUN: 	load_scib_tx_mail_box("[INIT]    "); break;		
					case STATE_GO_STOP: 	load_scib_tx_mail_box("[GO_STOP] "); break;		
					case STATE_WAIT_BREAK_OFF: load_scib_tx_mail_box("STATE_WAIT_BREAK_OFF"); break;	
					default: 				load_scib_tx_mail_box("Unknown State"); break;
				}
			}
			return;
		}
		else if(addr == 902){	//	내부 변수 read
			check = (int)data;

			switch( check ){
			case 0 :
				temp = (int)(floor(Freq_out +0.5));
				snprintf( str,10,"Fq=%3d[hz]",temp); load_scib_tx_mail_box(str);
				break;

			case 1 :
				temp = (int)(floor(rpm +0.5));
				snprintf( str,10,"RPM =%4d ",temp);	load_scib_tx_mail_box(str);
				break;
			case 2 :
				temp = (int)(floor(Vdc +0.5));
				snprintf( str,10," VDC =%4d",temp);	load_scib_tx_mail_box(str);
				break;
			case 3 :
				temp = (int)(floor( RMS_Ia * 10 + 0.5 ) );
				snprintf( str,10,"I1  =%2d.%d ",temp/10, temp%10); load_scib_tx_mail_box(str);
				break;
			case 4 :
				temp = (int)(floor( RMS_Ib * 10 + 0.5 ) );
				snprintf( str,10,"I2  =%2d.%d ",temp/10, temp%10); load_scib_tx_mail_box(str);
				break;
			case 5 : // Reset;
				gMachineState = STATE_POWER_ON;
				Nop();
				asm (" .ref _c_int00"); // ;Branch to start of boot.asm in RTS library
				asm (" LB _c_int00"); // ;Branch to start of boot.asm in RTS library
				break;
			default:
				break;
			}
			
			// check 에 따른 변수를 포인터로 두어서 처리 한다. 
		//	snprintf( str,30,"\n Vdc =%10.3e \n",Vdc);	load_scib_tx_mail_box(str); 
			return;
		}
		else if(addr == 903){	//	내부 변수 read // EEPROM TRIP DATA
			check = (int)data;

			if( data == 0 ){
				snprintf( str,4,"%03d:",TripInfoNow.CODE);
				load_scib_tx_mail_box(str); delay_msecs(180);

				load_scib_tx_mail_box(TripInfoNow.MSG); delay_msecs(220);
				load_scib_tx_mail_box(TripInfoNow.TIME); delay_msecs(180);

				dbtemp = TripInfoNow.HZ;
				temp = (int)(floor(dbtemp +0.5));				
				snprintf( str,10,"Fq=%3d[hz]",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);

				dbtemp = TripInfoNow.VDC;
				temp = (int)(floor(dbtemp +0.5));
				snprintf( str,10," VDC =%4d",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);

				dbtemp = TripInfoNow.CURRENT;
				temp = (int)(floor(dbtemp +0.5));
				snprintf( str,10,"I1  =%4d ",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);

				dbtemp = TripInfoNow.DATA;
				temp = (int)(floor(dbtemp +0.5));
				snprintf( str,10," DATA=%4d",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);
			}
			else{

		       TripData = (TRIP_INFO*)malloc(sizeof(TRIP_INFO));
		       GetTripInfo(check + 1,TripData);

				strncpy(gStr1,TripInfoNow.MSG,20);
			
				snprintf( str,4,"%03d:",TripData->CODE);
				load_scib_tx_mail_box(str); delay_msecs(180);

				load_scib_tx_mail_box(TripData->MSG); delay_msecs(220);
				load_scib_tx_mail_box(TripData->TIME); delay_msecs(180);

				dbtemp = TripData->HZ;
				temp = (int)(floor(dbtemp +0.5));				
				snprintf( str,10,"Fq=%3d[hz]",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);

				dbtemp = TripData->VDC;
				temp = (int)(floor(dbtemp +0.5));
				snprintf( str,10," VDC =%4d",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);

				dbtemp = TripData->CURRENT;
				temp = (int)(floor(dbtemp +0.5));
				snprintf( str,10,"I1  =%4d ",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);

				dbtemp = TripData->DATA;
				temp = (int)(floor(dbtemp +0.5));
				snprintf( str,10," DATA=%4d",temp);	
				load_scib_tx_mail_box(str);	delay_msecs(180);

				free(TripData);
			}
			return;
		}
		else if(addr == 904){	 // DATE & TIME SET
			check = (int)data;

			switch( check ){
			case 0:
				TimeInput[0] = scib_rx_msg_box[10];
				TimeInput[1] = scib_rx_msg_box[11];
				TimeInput[2] = scib_rx_msg_box[12];
				TimeInput[3] = scib_rx_msg_box[13];
				TimeInput[4] = scib_rx_msg_box[14];
				TimeInput[5] = scib_rx_msg_box[15];
				break;
			case 1:
				TimeInput[6] = scib_rx_msg_box[10];
				TimeInput[7] = scib_rx_msg_box[11];
				TimeInput[8] = scib_rx_msg_box[12];
				TimeInput[9] = scib_rx_msg_box[13];
				TimeInput[10] = scib_rx_msg_box[14];
				TimeInput[11] = scib_rx_msg_box[15];
				delay_msecs(50);
				WriteTimeToDS1307(TimeInput);
				load_scib_tx_mail_box("Date & Time Saved");
				break;
			case 2:
		//		load_scib_tx_mail_box("WAIT FOR CLEAR DATA!");
		//		delay_msecs(180);
				ClearTripDataToEeprom();
				break;
			}
			return;
		}
		else if(addr == 905){	// RUN & STOP
			check = (int)data;
				
			switch( check ){
			case 0:
				* sci_cmd = CMD_START;
				* sci_ref = code_btn_start_ref;
				break;
			case 1:
				* sci_cmd = CMD_STOP;
				* sci_ref = 0.0;
				break;
			case 2:
				* sci_cmd = CMD_SPEED_UP;
				break;
			case 3:
				* sci_cmd = CMD_SPEED_DOWN;
				break;
			default:
				* sci_cmd = CMD_NULL;
				break;
			}
			return;
		}
		else if(addr == 906){
			GetTimeAndDateStr(str);
			load_scib_tx_mail_box(str);
			return;
		}
		else if (( addr > 979) && ( addr < 996)){
			check = addr - 980;
			snprintf( str,19,"adc =%4d",adc_result[check]);
			load_scib_tx_mail_box(str);
			delay_msecs(10);
			return;
		}

		check = get_code_information( addr, CMD_READ_DATA , & code_inform);
	
		if( check == 0 ){
			check = (int)data;

			switch(check)
			{
			case 0:
				snprintf( str,19,"CODE=%4d",addr);
				load_scib_tx_mail_box(str);
				 delay_msecs(10);
				break;
			case 1:
				load_scib_tx_mail_box(code_inform.disp);delay_msecs(10);
				break;
			case 2: 
				if( code_inform.type == TYPE_DOUBLE ){
					snprintf( str,20,"Data =%10.3e",code_inform.code_value.doubles);
				}
				else{
					snprintf( str,20,"Data =%10d",code_inform.code_value.ints);
				}
				load_scib_tx_mail_box(str);	delay_msecs(10);
				break;
			default:
				snprintf( str,19,"CODE=%4d",addr);
				load_scib_tx_mail_box(str);delay_msecs(10);
				load_scib_tx_mail_box(code_inform.disp);delay_msecs(10);

				if( code_inform.type == TYPE_DOUBLE )
					snprintf( str,20,"Data =%10.3e",code_inform.code_value.doubles);
				else
					snprintf( str,20,"Data =%10d",code_inform.code_value.ints);

				load_scib_tx_mail_box(str);	delay_msecs(10);				 
	
				break;
			}	
		}
		else{
			load_scib_tx_mail_box("Error Invalid Address");delay_msecs(10);		
		}
		return;
	}
}
예제 #12
0
void TripProc( )
{
	int iCommand;
	int LoopCtrl;
	int temp;
	double fReference;
	double dbtemp;
	char str[30];

	str[29] = 0;
	EALLOW;
	GpioCtrlRegs.GPAMUX1.bit.GPIO0 	= 0;  // GPIO0 = PWM1A
	GpioCtrlRegs.GPAMUX1.bit.GPIO1 	= 0;  // GPIO1 = PWM1B
	GpioCtrlRegs.GPAMUX1.bit.GPIO2 	= 0;  // GPIO2 = PWM2A
	GpioCtrlRegs.GPAMUX1.bit.GPIO3 	= 0;  // GPIO3 = PWM2B
	GpioCtrlRegs.GPAMUX1.bit.GPIO4 	= 0;  // GPIO4 = PWM3A
	GpioCtrlRegs.GPAMUX1.bit.GPIO5 	= 0;  // GPIO5 = PWM3B

	GpioCtrlRegs.GPAMUX1.bit.GPIO6 	= 0;  // GPIO4A
	GpioCtrlRegs.GPAMUX1.bit.GPIO7 	= 0;  // GPIO4B
	GpioCtrlRegs.GPAMUX1.bit.GPIO8 	= 0;  // GPIO5A
	GpioCtrlRegs.GPAMUX1.bit.GPIO9 	= 0;  // GPIO5B
	GpioCtrlRegs.GPAMUX1.bit.GPIO10	= 0;  // GPIO6A
	GpioCtrlRegs.GPAMUX1.bit.GPIO11	= 0;  // GPIO6B

	GpioCtrlRegs.GPADIR.bit.GPIO0 	= 1;  // GPIO0 = Output
	GpioCtrlRegs.GPADIR.bit.GPIO1 	= 1;  // GPIO1 = Output
	GpioCtrlRegs.GPADIR.bit.GPIO2 	= 1;  // GPIO2 = Output
	GpioCtrlRegs.GPADIR.bit.GPIO3 	= 1;  // GPIO3 = Output
	GpioCtrlRegs.GPADIR.bit.GPIO4 	= 1;  // GPIO4 = Output
	GpioCtrlRegs.GPADIR.bit.GPIO5 	= 1;  // GPIO5 = Output

	GpioCtrlRegs.GPADIR.bit.GPIO6 	= 1;  // GPIO4A
	GpioCtrlRegs.GPADIR.bit.GPIO7 	= 1;  // GPIO4B
	GpioCtrlRegs.GPADIR.bit.GPIO8 	= 1;  // GPIO5A
	GpioCtrlRegs.GPADIR.bit.GPIO9 	= 1;  // GPIO5B
	GpioCtrlRegs.GPADIR.bit.GPIO10 	= 1;  // GPIO6A
	GpioCtrlRegs.GPADIR.bit.GPIO11 	= 1;  // GPIO6B


	GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO1 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO2 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO3 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO5 = 1;  // Set Output

	GpioDataRegs.GPACLEAR.bit.GPIO6 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO7 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO8 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO9 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO10 = 1;  // Set Output
	GpioDataRegs.GPACLEAR.bit.GPIO11 = 1;  // Set Output

	EDIS;

	gMachineState = STATE_TRIP;

	MAIN_CHARGE_OFF;					// Main Charge Relay Off
	init_charge_flag=0;
	INIT_CHARGE_CLEAR;
	TRIP_OUT_ON;
		
	GetTimeAndDateStr(str);
	strncpy( TripInfoNow.TIME,str,20);

//	SaveTripDataToEeprom();  debug_jsk

	load_sci_tx_mail_box("TRP"); delay_msecs(20);
	snprintf( str,4,"%03d:",TripInfoNow.CODE);
	load_sci_tx_mail_box(str); delay_msecs(20);

	load_sci_tx_mail_box(TripInfoNow.MSG); delay_msecs(20);

	load_sci_tx_mail_box( TripInfoNow.TIME) ; delay_msecs(20);

	dbtemp = TripInfoNow.HZ;
	temp = (int)(floor(dbtemp +0.5));				
	snprintf( str,10,"Fq=%3d[hz]",temp);	
	load_sci_tx_mail_box(str);	delay_msecs(20);

	dbtemp = TripInfoNow.VDC;
	temp = (int)(floor(dbtemp +0.5));
	snprintf( str,10," VDC =%4d",temp);	
	load_sci_tx_mail_box(str);	delay_msecs(20);

	dbtemp = TripInfoNow.CURRENT;
	temp = (int)(floor(dbtemp +0.5));
	snprintf( str,10,"I1  =%4d ",temp);	
	load_sci_tx_mail_box(str);	delay_msecs(20);

	dbtemp = TripInfoNow.DATA;
	temp = (int)(floor(dbtemp +0.5));
	snprintf( str,10," DATA=%4d",temp);
	load_sci_tx_mail_box(str);	delay_msecs(20);

	LoopCtrl = CMD_NULL;
	while( LoopCtrl != CMD_RESET)
	{
		get_command( & iCommand, & fReference);	// Command를 입력 받음 				
		if( iCommand == CMD_RESET) LoopCtrl = CMD_RESET;
		Nop();
	}

	delay_msecs(50);
	while( LoopCtrl == CMD_RESET)
	{
		get_command( & iCommand, & fReference);	// Command를 입력 받음 				
		if( iCommand == CMD_STOP) LoopCtrl = CMD_STOP;
		Nop();
	}

	for( ; ; ) // system reset 
	{
		gMachineState = STATE_TRIP;
		Nop();
		asm (" .ref _c_int00"); // ;Branch to start of boot.asm in RTS library
		asm (" LB _c_int00"); // ;Branch to start of boot.asm in RTS library
	}
}
예제 #13
0
파일: code_proc.c 프로젝트: eunwho/b2inv
int SaveDataProc(int addr, double data)
{
	int cmd,i,return_value;
	char SciBuf[30]={0};
	char str[30];
	UNION32 u32data,u32data2;

	return_value = 0;

	cmd = CMD_READ_DATA;

	i = get_code_information( addr,cmd,&code_inform); 

	if( i != 0 ) goto _SAVE_ERROR_INVALID_ADDR;   

	if( addr >= 800 ){

		if( data < 1.22 ) goto _SAVE_ERROR_INVALID_DATA; 
		if( data > 1.24 ) goto _SAVE_ERROR_INVALID_DATA; 
		switch(addr)
		{
		case CODE_Data_Check: 	return_value = check_backup_data();	break;
		case CODE_Data_Backup:
			strncpy(str,"Wait for Data Backup",20);
			load_sci_tx_mail_box(str); delay_msecs(20);
			save_backup_data();
			strncpy(str,"Wait for Error Check",20);
			load_sci_tx_mail_box(str);  delay_msecs(20);

			break;
		case CODE_Data_Load:
			strncpy(str,"Wait for Data Load !",20);
			load_sci_tx_mail_box(str); delay_msecs(20);	
			backup_data_load();
			break;
		case CODE_Data_Init:
			strncpy(str,"Wait For Data Init !",20);
			load_sci_tx_mail_box(str); delay_msecs(20);
			init_eprom_data();
			strncpy(str,"Data Init OK !      ",20);
			load_sci_tx_mail_box(str); delay_msecs(20);
			break;
		case CODE_get_adc_offset:	get_adc_offset();	break;
		default:
			goto _SAVE_ERROR_INVALID_ADDR;
		}
		return return_value;
	}

	if( code_inform.type == TYPE_INTEGER){
		if( (code_inform.code_min.ints)  > (int)data ){
			goto _SAVE_ERROR_DATA_UNDER;
		}
		else if( (code_inform.code_max.ints) < (int)data){
			goto _SAVE_ERROR_DATA_OVER;
		}
		else {
//			u32data.word.word1 = 0;
			u32data.word.word0 = (int)data;
			read_eprom_data( addr, & u32data2);
			if( u32data.word.word0 != u32data2.word.word0 ){
				write_code_2_eeprom( addr, u32data);
				read_eprom_data( addr, & u32data2);				
				if( u32data.word.word0 != u32data2.word.word0 ) goto _EEPROM_WRITE_ERROR;
				code_inform.code_value.ints = (int)data;
				cmd = CMD_WRITE_RAM;
				get_code_information( addr,cmd, & code_inform);

				load_sci_tx_mail_box("OK write success") ;
			}
			else{
				load_sci_tx_mail_box("Equal Data write skipped");
			}
			return 0;
		}	 
	}	
	else {		//  code_inform->Type == TYPE_DOUBLE
		if( ( code_inform.code_min.doubles) > data ){
			goto _SAVE_ERROR_DATA_UNDER;
		}
		else if( ( code_inform.code_max.doubles) < data ){
			goto _SAVE_ERROR_DATA_OVER;
		}			
		else {
			u32data.dword = data;
			read_eprom_data( addr, & u32data2);
			if( u32data.dword != u32data2.dword ){
				write_code_2_eeprom( addr, u32data);
				read_eprom_data( addr, & u32data2);

				if( u32data.dword != u32data2.dword ) goto _EEPROM_WRITE_ERROR;

				code_inform.code_value.doubles = data;
				cmd = CMD_WRITE_RAM;
				get_code_information( addr,cmd, & code_inform);

				// CheckSum Save
				u32data.dword = CheckSum();
				EepromSaveFlag = 1;
				write_code_2_eeprom(EPROM_ADDR_CHECKSUM, u32data);
				EepromSaveFlag = 0;

				load_sci_tx_mail_box("OK write success") ;
			}
			else{
				load_sci_tx_mail_box("Equal Data write skipped");
			}
			return 0;
		}	 
	}	

_SAVE_ERROR_INVALID_ADDR:
//	strcpy(SciBuf, "ADDR");
	strcpy(SciBuf,"Invalid Address" );
	load_sci_tx_mail_box(SciBuf) ;
	return -1;

_SAVE_ERROR_DATA_UNDER:

//	strcpy(SciBuf, "UNDE");

	strcpy(SciBuf,"Input data under" );
	load_sci_tx_mail_box(SciBuf) ;
	return -1;

_SAVE_ERROR_DATA_OVER:
//	strcpy(SciBuf, "OVER");
	strcpy(SciBuf,"Input data over" );
	load_sci_tx_mail_box(SciBuf) ;
	return -1;

_SAVE_ERROR_INVALID_DATA:
//	strcpy(SciBuf, "DATA");
	strcpy(SciBuf,"Invalid data " );
	load_sci_tx_mail_box(SciBuf) ;
	return -1;

_EEPROM_WRITE_ERROR:
//	strcpy(SciBuf, "DATA");
	strcpy(SciBuf,"Eeprom write error" );
	load_sci_tx_mail_box(SciBuf) ;
	return -1;
}
/*****
 * DoTest_Characterize() - Perform the Characterization test
 * 
 * This function starts the duty cycle at the minimum duty cycle and
 * then increases it to the max duty cycle for the test.
 * Samples are collected into the global array sample[].  
 * The function toggles the TEST_RUNNING signal high for the duration
 * of the test as a debug aid and adjusts the global "pwm_duty"
 *
 * The test also sets the global ADC min and max counts to
 * help limit the ADC counts to the active range for the circuit
 *****/
int DoTest_Characterize(void) {
	XStatus Status; // Xilinx return status
	unsigned tss; // starting timestamp
	u16 adc_1, adc_2; // holds the ADC count - sampled twice and averaged
	u16 adc_cnt; // ADC counts to display
	int n; // number of samples
	Xuint32 freq, dutyfactor; // current frequency and duty factor


	// stabilize the PWM output (and thus the lamp intensity) at the
	// minimum before starting the test
	pwm_duty = PWM_STEPDC_MIN;
	Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
	if (Status == XST_SUCCESS) {
		PWM_Start(&PWMTimerInst);
	} else {
		return -1;
	}
	delay_msecs(1000);

	// sweep the duty cycle from STEPDC_MIN to STEPDC_MAX
	smpl_idx = PWM_STEPDC_MIN;
	n = 0;
	tss = timestamp;
	while (smpl_idx <= PWM_STEPDC_MAX)
	{
		Status = PWM_SetParams(&PWMTimerInst, pwm_freq, smpl_idx);
		if (Status == XST_SUCCESS)
		{
			PWM_Start(&PWMTimerInst);
		} else {
			return -1;
		}
		// sample the ADC twice and average the readings
		adc_1 = PmodCtlSys_readADC(&SPIInst);
		delay_msecs(1);
		adc_2 = PmodCtlSys_readADC(&SPIInst);
		adc_cnt = (adc_1 + adc_2) / 2;
		sample[smpl_idx++] = adc_cnt;

		n++;
		delay_msecs(20);
	}
	adc_smple_interval = (timestamp - tss) / smpl_idx;

	// initialize the ADC min and max counts from the saved data
	ADC_min_cnt = ADC_max_cnt = 0;
	for (n = PWM_STEPDC_MIN; n <= PWM_STEPDC_MAX; n++) {
		if (sample[n] < ADC_min_cnt)
			ADC_min_cnt = sample[n];

		if (sample[n] > ADC_max_cnt)
			ADC_max_cnt = sample[n];
	}
	ADC_max_vout = PmodCtlSys_ADCVolts(ADC_min_cnt);
	ADC_min_vout = PmodCtlSys_ADCVolts(ADC_max_cnt);

	// initialize the PWM min and max counts - these are constants so can be calculated here
	// count = ((pwm duty cycle * PLB clock frequency[Hz]) / pwm frequency[Hz]) - 2
	PWM_GetParams(&PWMTimerInst, &freq, &dutyfactor);
	PWM_min_cnt = ((PWM_STEPDC_MIN * .01 * PLB_CLOCK_FREQ_HZ) / freq) - 2;
	PWM_max_cnt = ((PWM_STEPDC_MAX * .01 * PLB_CLOCK_FREQ_HZ) / freq) - 2;
	return n;
}
예제 #15
0
int main()
{
    XStatus 	Status;
    u32			btnsw = 0x00000000, old_btnsw = 0x000000FF;
    int			rotcnt, old_rotcnt = 0x1000;
    Test_t		test, next_test;
    is_scaled = false;
    bool lcd_initial = true;
    char 		sp[20];
    u16 row = 1;
    u16 col = 2;
    bool calc_done = false;
    freq_min_cnt = 3000;


    // initialize devices and set up interrupts, etc.
    Status = do_init();
    if (Status != XST_SUCCESS)
    {
        LCD_setcursor(1,0);
        LCD_wrstring("****** ERROR *******");
        LCD_setcursor(2,0);
        LCD_wrstring("INIT FAILED- EXITING");
        exit(XST_FAILURE);
    }

    // initialize the variables
    timestamp = 0;
    pwm_freq = PWM_FREQUENCY;
    next_test = TEST_INVALID;

    prop_gain     = PROP_INIT_GAIN;
    integral_gain = INT_INIT_GAIN;
    deriv_gain    = DERIV_INIT_GAIN;


    // Enable the Microblaze caches and kick off the processing by enabling the Microblaze
    // interrupt.  This starts the FIT timer which updates the timestamp.
    if (USE_ICACHE == 1)
    {
        microblaze_invalidate_icache();
        microblaze_enable_icache();
    }
    if (USE_DCACHE == 1)
    {
        microblaze_invalidate_dcache();
        microblaze_enable_dcache();
    }
    microblaze_enable_interrupts();

    // display the greeting
    LCD_setcursor(1,0);
    LCD_wrstring("PWM Ctrl sys");
    LCD_setcursor(2,0);
    LCD_wrstring("Erik R, Caren Z");
    NX3_writeleds(0xFF);
    //delay_msecs(2500);

    LCD_clrd();
    LCD_setcursor(1,0);
    LCD_wrstring("Characterizing..");
    //Run the LED characterization routine to establish sensor min's and max's
    DoTest_Characterize();
    LCD_setcursor(2,0);
    LCD_wrstring("Done.");



    NX3_writeleds(0x00);

    delay_msecs(500);
    //set initial screen
    // main loop - there is no exit except by hardware reset
    while (1)
    {
        //set Vin to min or max depending on switch 3 value
        if (btnsw & msk_SWITCH3)
        {
            pwm_duty = MAX_DUTY;
            dc_start = MAX_DUTY;
        }
        else
        {
            pwm_duty = MIN_DUTY;
            dc_start = MIN_DUTY;
        }

        // Write values to display when in "idle" state
        if (lcd_initial)
        {
            LCD_clrd();
            LCD_setcursor(1,0);
            LCD_wrstring("P:   I:   D:   ");
            LCD_setcursor(1,2);
            LCD_setcursor(2,0);
            LCD_wrstring("SP:+     OFF:   ");
            lcd_initial = false;
            LCD_setcursor(1,2);
        }
        no_test_LCD();
        NX3_readBtnSw(&btnsw);
        // Set which control measurement we're using
        if (btnsw & msk_BTN_NORTH)
        {
            // increment to the next selection.  If we're at the last enum, set it to the 1st (proportional)
            if (PID_current_sel == OFFSET) PID_current_sel = PROPORTIONAL;
            else PID_current_sel = (Control_t)((int)(PID_current_sel+1));  //casting to allow increment

            // cursor control logic
            if (PID_current_sel == PROPORTIONAL)
            {
                row = 1;
                col = 2;
            }
            else if (PID_current_sel == INTEGRAL)
            {
                row = 1;
                col = 7;
            }
            else if (PID_current_sel == DERIVATIVE)
            {
                row = 1;
                col = 12;
            }
            else if (PID_current_sel == OFFSET)
            {
                row  = 2;
                col  = 13;
            }
        }

        delay_msecs(20);
        //set cursor location and turn on cursor
        LCD_setcursor(row,col);
        LCD_docmd(LCD_DISPLAYONOFF, LCD_CURSOR_ON);

        if (btnsw & msk_BTN_EAST)
        {
            if (PID_current_sel == PROPORTIONAL)     prop_gain     += GAIN_INCREMENT;
            else if (PID_current_sel == INTEGRAL)    integral_gain += GAIN_INCREMENT;
            else if (PID_current_sel == DERIVATIVE)  deriv_gain    += GAIN_INCREMENT;
            else                                     offset        += GAIN_INCREMENT;
        }
        if (btnsw & msk_BTN_WEST)
        {
            if (PID_current_sel == PROPORTIONAL)     prop_gain     -= GAIN_INCREMENT;
            else if (PID_current_sel == INTEGRAL)    integral_gain -= GAIN_INCREMENT;
            else if (PID_current_sel == DERIVATIVE)  deriv_gain    -= GAIN_INCREMENT;
            else                                     offset        -= GAIN_INCREMENT;
        }


        // read sw[1:0] to get the test to perform.
        NX3_readBtnSw(&btnsw);
        test = btnsw & (msk_SWITCH1 | msk_SWITCH0);

        ROT_readRotcnt(&rotcnt);
        if (rotcnt != old_rotcnt)
        {
            //scale rotary count to setpoint values
            LCD_docmd(LCD_DISPLAYONOFF, LCD_CURSOR_OFF);
            setpoint = MAX(VOLT_MIN, MIN((rotcnt/SETPOINT_SCALE), VOLT_MAX));
            voltstostrng(setpoint, sp);
            old_rotcnt = rotcnt;
            LCD_setcursor(2, 3);
            LCD_wrstring(sp);
            LCD_setcursor(2, 3);
            LCD_wrstring('+');
        }

        if (test == TEST_T_CALLS) //unused
        {
            next_test = TEST_INVALID;
            lcd_initial = true;
            delay_msecs(3000);

        }


        else if ((test == TEST_BANG ) || (test == TEST_PID))  // Test 1 & 2 - control methods Bang Bang and PID
        {
            Xfloat32	v;
            char		s[20];

            // start the test on the rising edge of the Rotary Encoder button press
            // the test will write the light detector samples into the global "sample[]"
            // the samples will be sent to stdout when the Rotary Encoder button
            // is released
            //
            // NOTE ON DETECTING BUTTON CHANGES:
            // btnsw ^ old_btnsw will set the bits for all of the buttons and switches that
            // have changed state since the last time the buttons and switches were read
            // msk_BTN_ROT & btnsw will test whether the rotary encoder was one of the
            // buttons that changed from 0 -> 1

            if ((btnsw ^ old_btnsw) && (msk_BTN_ROT & btnsw))  // do the step test and dump data
            {

                /*Running Test (rotary pushbutton pushed): Show which control algorithm is running and
                  display instructions for running test and uploading data.*/

                if (test != next_test)
                {
                    if (test == TEST_BANG)
                    {
                        strcpy(s, "|BANG|Long Press");
                    }
                    else
                    {
                        strcpy(s, "|PID|Long Press");
                    }
                    delay_msecs(100);
                    LCD_clrd();
                    LCD_setcursor(1,0);
                    LCD_wrstring(s);
                    LCD_setcursor(2,0);
                    LCD_wrstring("RotBtn to start");
                }

                NX3_writeleds(0x01);
                if (test == TEST_BANG)  // perform bang bang calculations
                {
                    calc_bang();
                }
                else  // perform PID tests
                {
                    calc_PID();
                }
                NX3_writeleds(0x00);

                //FEATURE: wait for user input to send data over
                NX3_readBtnSw(&btnsw);
                if ((btnsw ^ old_btnsw) && (msk_BTN_ROT & btnsw))
                {
                    // light "Transfer" LED to indicate that data is being transmitted
                    // Show the traffic on the LCD
                    NX3_writeleds(0x02);
                    LCD_clrd();
                    LCD_setcursor(1, 0);
                    LCD_wrstring("Sending Data....");
                    LCD_setcursor(2, 0);
                    LCD_wrstring("S:    DATA:     ");

                    // print the descriptive heading followed by the data
                    if (test == TEST_BANG)
                    {
                        xil_printf("\n\rBang Bang! Test Data\t\tAppx. Sample Interval: %d msec\n\r", frq_smple_interval);
                    }
                    else
                    {
                        xil_printf("\n\rPID Test Data\t\tAppx. Sample Interval: %d msec\n\r", frq_smple_interval);
                    }

                    // trigger the serial charter program)
                    xil_printf("===STARTPLOT===\n");

                    // start with the second sample.  The first sample is not representative of
                    // the data.  This will pretty-up the graph a bit
                    for (smpl_idx = 1; smpl_idx < NUM_FRQ_SAMPLES; smpl_idx++)
                    {
                        u16 count;

                        count = sample[smpl_idx];
                        if (count > 4096)
                            count = 4095;

                        v = (-3.3 / 4095.0) * (count) + 3.3;

                        voltstostrng(v, s);
                        xil_printf("%d\t%d\t%s\n\r", smpl_idx, count, s);

                        LCD_setcursor(2, 2);
                        LCD_wrstring("   ");
                        LCD_setcursor(2, 2);
                        LCD_putnum(smpl_idx, 10);
                        LCD_setcursor(2, 11);
                        LCD_wrstring("     ");
                        LCD_setcursor(2, 11);
                        LCD_putnum(count, 10);
                    }

                    // stop the serial charter program
                    xil_printf("===ENDPLOT===\n");

                    NX3_writeleds(0x00);
                    old_btnsw = btnsw;
                    next_test = TEST_INVALID;
                    lcd_initial = true;
                    delay_msecs(3000);
                }
            }  // do the step test and dump data

        }
        else if (test == TEST_CHARACTERIZE)  // Test 3 - Characterize Response
        {

            // start the test on the rising edge of the Rotary Encoder button press
            // the test will write the samples into the global "sample[]"
            // the samples will be sent to stdout when the Rotary Encoder button
            // is released
            NX3_readBtnSw(&btnsw);
            if ((btnsw ^ old_btnsw) && (msk_BTN_ROT & btnsw))
            {
                LCD_docmd(LCD_DISPLAYONOFF, LCD_CURSOR_OFF);
                // light "Run" (rightmost) LED to show the test has begun
                // and do the test.  The test will return when the measured samples array
                // has been filled.  Turn off the rightmost LED after the data has been
                if (test != next_test)
                {
                    LCD_clrd();
                    LCD_setcursor(1,0);
                    LCD_wrstring("|CHAR|Long Press");
                    LCD_setcursor(2,0);
                    LCD_wrstring("RotBtn to start");
                }
                // captured to let the user know he/she can release the button
                NX3_readBtnSw(&btnsw);
                if ((msk_BTN_ROT & btnsw) && (!calc_done))
                {
                    NX3_writeleds(0x01);
                    LCD_clrd();
                    LCD_setcursor(1,0);
                    LCD_wrstring("Characterizing..");
                    DoTest_Characterize();
                    LCD_setcursor(2,0);
                    LCD_wrstring("Done.");
                    NX3_writeleds(0x00);
                    delay_msecs(750);
                    LCD_setcursor(2,8);
                    LCD_wrstring("<OK>");
                    calc_done = true;
                    next_test = test;
                }

                NX3_readBtnSw(&btnsw);
                if (msk_BTN_ROT & btnsw)
                {
                    // light "Transfer" LED to indicate that data is being transmitted
                    // Show the traffic on the LCD
                    NX3_writeleds(0x02);
                    LCD_clrd();
                    LCD_setcursor(1, 0);
                    LCD_wrstring("Sending Data....");
                    LCD_setcursor(2, 0);
                    LCD_wrstring("S:    DATA:     ");

                    xil_printf("\n\rCharacterization Test Data\t\tAppx. Sample Interval: %d msec\n\r", frq_smple_interval);

                    // trigger the serial charter program)
                    xil_printf("===STARTPLOT===\n\r");

                    for (smpl_idx = STEPDC_MIN; smpl_idx <= STEPDC_MAX; smpl_idx++)
                    {
                        u16 		count;
                        Xfloat32	v;
                        char		s[10];

                        count = sample[smpl_idx];
                        if (count > 4096)
                            count = 4095;

                        v = (-3.3 / 4095.0) * (count) + 3.3;

                        voltstostrng(v, s);
                        xil_printf("%d\t%d\t%s\n\r", smpl_idx, count, s);

                        LCD_setcursor(2, 2);
                        LCD_wrstring("   ");
                        LCD_setcursor(2, 2);
                        LCD_putnum(smpl_idx, 10);
                        LCD_setcursor(2, 11);
                        LCD_wrstring("     ");
                        LCD_setcursor(2, 11);
                        LCD_putnum(count, 10);
                    }

                    // stop the serial charter program
                    xil_printf("===ENDPLOT===\n\r");

                    NX3_writeleds(0x00);
                    old_btnsw = btnsw;
                    next_test = TEST_INVALID;
                    delay_msecs(1000);
                    lcd_initial = true;
                    delay_msecs(3000);
                }
            }  // do the step test and dump data

        } // Test 3 - Characterize Response
        else  // outside the current test range - blink LED's and hang
        {
            // should never get here but just in case
            NX3_writeleds(0xFF);
            delay_msecs(2000);
            NX3_writeleds(0x00);
        }
        // wait a bit and start again

        delay_msecs(100);
    }  // while(1) loop
}  // end main()
/*****
 * DoTest_BB() - Perform Bang-Bang control
 * 
 * This function adjusts the global "pwm_duty" value to try to bring the
 * control system simulator closer to the ADC setpoint.  The initial state of the PWM
 * is derived from the global "init_high" flag. NUM_ADC_SAMPLES are collected
 * into the global array sample[] and the count returned.  The function toggles the TEST_RUNNING
 * signal high for the duration of the test as a debug aid.  An approximate
 * ADC sample interval is written to the global variable "adc_smpl_interval"
 *
 * Bang-bang control is the simplest form of closed loop control.  The PWM is turned either full-on
 * of full-off depending on whether the output is below or above the setpoint. 
 *
 * NOTE:  THIS ALGORIHM IS LEFT AS AN EXERCISE FOR THE PROGRAMMER
 *****/
int DoTest_BB(void)
{

	XStatus Status;         // Xilinx return status
	unsigned tss;           // starting timestamp
	u16 adc_1, adc_2; 		// holds the ADC count - sampled twice and averaged
	u16 adc_cnt; 			// ADC counts to display
	int n; 					// number of samples
    Xfloat32 setpoint_volts, adc_reading_volts;

	//The initial state of the PWM is derived from the global "init_high" flag.
	// true if inital state of test should be full-on, false otherwise
	if (init_high == true)
		pwm_duty = PWM_STEPDC_MAX;
	else
		pwm_duty = PWM_STEPDC_MIN;

	//Checks Status
	Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
	if (Status == XST_SUCCESS) {
		PWM_Start(&PWMTimerInst);
	} else {
		return -1;
	}
	delay_msecs(100);

	smpl_idx = 0;
	n = 0;
	tss = timestamp;

	//Calculate in volts our setpoint
	setpoint_volts = PmodCtlSys_ADCVolts(setpoint);
	////-------------------------------
	LCD_clrd();
	LCD_setcursor(1, 0);
	LCD_wrstring("BANG BANG");

	while (smpl_idx <= NUM_ADC_SAMPLES)
	{
		Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
		if (Status == XST_SUCCESS)
		{
			PWM_Start(&PWMTimerInst);
		}
		else {
			return -1;
		}

		//Sample the ADC and average the readings
		adc_1 = PmodCtlSys_readADC(&SPIInst);
		delay_msecs(1);
		adc_2 = PmodCtlSys_readADC(&SPIInst);
		adc_cnt = (adc_1 + adc_2) / 2;

		//Converting the ADC average into volts
		adc_reading_volts = PmodCtlSys_ADCVolts(adc_cnt);

		if (adc_reading_volts < setpoint_volts)
			pwm_duty = PWM_STEPDC_MIN; //input to 100% duty cycle
		else
			pwm_duty = PWM_STEPDC_MAX;

		//CHECK STATUS
		Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
		if (Status == XST_SUCCESS) {
			PWM_Start(&PWMTimerInst);
		} else {
			return -1;
		}

		//store in array
		sample[smpl_idx++] = adc_cnt;
		n++;
	}
	adc_smple_interval = (timestamp - tss) / smpl_idx;
	return n;

}
예제 #17
0
int main()
{
	XStatus 	Status;
	u32			btnsw = 0x00000000, old_btnsw = 0x000000FF;
	int			rotcnt, old_rotcnt = 0x1000;
	Test_t		test, next_test;
	is_scaled = false;
	
	// initialize devices and set up interrupts, etc.
 	Status = do_init();
 	if (Status != XST_SUCCESS)
 	{
 		LCD_setcursor(1,0);
 		LCD_wrstring("****** ERROR *******");
 		LCD_setcursor(2,0);
 		LCD_wrstring("INIT FAILED- EXITING");
 		exit(XST_FAILURE);
 	}

	// initialize the variables
	timestamp = 0;							
	pwm_freq = PWM_FREQUENCY;
	pwm_duty = STEPDC_MIN;
	next_test = TEST_INVALID;

	// Enable the Microblaze caches and kick off the processing by enabling the Microblaze
	// interrupt.  This starts the FIT timer which updates the timestamp.
	if (USE_ICACHE == 1)
	{
		microblaze_invalidate_icache();
		microblaze_enable_icache();
	}
	if (USE_DCACHE == 1)
	{
		microblaze_invalidate_dcache();
		microblaze_enable_dcache();
	}
	microblaze_enable_interrupts();
	 	  	
 	// display the greeting   
    LCD_setcursor(1,0);
    LCD_wrstring("PmodCtlSys Test ");
	LCD_setcursor(2,0);
	LCD_wrstring("R3.0 by Robin M.");
	NX3_writeleds(0xFF);
	//Run the LED characterization routine to establish sensor min's and max's
    DoTest_Characterize();
	NX3_writeleds(0x00);
       
    // main loop - there is no exit except by hardware reset
	while (1)
	{ 
		// read sw[1:0] to get the test to perform.
		NX3_readBtnSw(&btnsw);
		test = btnsw & (msk_SWITCH1 | msk_SWITCH0);
			
		if (test == TEST_TRACKING)  // Test 0 = Track PWM voltage
		{
			// write the static info to display if necessary
			if (test != next_test)
			{
				LCD_clrd();
				LCD_setcursor(1,0);
				LCD_wrstring("| TRK| Vi: sx.xx");
				LCD_setcursor(2,0);
				LCD_wrstring("Vo:sx.xx C:sxxxx");
			}
				 						
			// read rotary count and handle duty cycle changes
			// limit duty cycle to between STEPDC_MIN and STEPDC_MAX
			// PWM frequency does not change in this test
			ROT_readRotcnt(&rotcnt);
			if (rotcnt != old_rotcnt)
			{
				pwm_duty = MAX(STEPDC_MIN, MIN(rotcnt, STEPDC_MAX));
				old_rotcnt = rotcnt;
			}
			DoTest_Track();
			next_test = TEST_TRACKING;
		}   // Test 0 = Track PWM voltage
		else if ((test == TEST_STEPHILO) || (test == TEST_STEPLOHI))  // Test 1 & 2 - Step response 
		{
			Xfloat32	v;
			char		s[20];	
			
			// write the static info to the display if necessary
			if (test != next_test)
			{
				if (test == TEST_STEPHILO)
				{
					strcpy(s, "|HILO|Press RBtn");
				}
				else
				{
					strcpy(s, "|LOHI|Press RBtn");
				}
				
				LCD_clrd();
				LCD_setcursor(1,0);
				LCD_wrstring(s);
				LCD_setcursor(2,0);
				LCD_wrstring("LED OFF-Release ");
			}
			
			// start the test on the rising edge of the Rotary Encoder button press
			// the test will write the light detector samples into the global "sample[]"
			// the samples will be sent to stdout when the Rotary Encoder button
			// is released
			//
			// NOTE ON DETECTING BUTTON CHANGES:
			// btnsw ^ old_btnsw will set the bits for all of the buttons and switches that
			// have changed state since the last time the buttons and switches were read
			// msk_BTN_ROT & btnsw will test whether the rotary encoder was one of the
			// buttons that changed from 0 -> 1	
			if ((btnsw ^ old_btnsw) && (msk_BTN_ROT & btnsw))  // do the step test and dump data  
			{										
				// light "Run" (rightmost) LED to show the test has begun
				// and do the test.  The test will return when the measured samples array
				// has been filled.  Turn off the rightmost LED after the data has been 
				// captured to let the user know he/she can release the button
				NX3_writeleds(0x01);
				if (test == TEST_STEPHILO)  // perform High->Low step test
				{				
					DoTest_Step(STEPDC_MAX);
				}
				else  // perform Low->High step
				{
					DoTest_Step(STEPDC_MIN);
				}
				NX3_writeleds(0x00);
				
				// wait for the Rotary Encoder button to be released
				// and then send the sample data to stdout
				do
				{
					NX3_readBtnSw(&btnsw);
					delay_msecs(10);
				} while ((btnsw & msk_BTN_ROT) == 0x80);
				
				// light "Transfer" LED to indicate that data is being transmitted
				// Show the traffic on the LCD
				NX3_writeleds(0x02);
				LCD_clrd();
				LCD_setcursor(1, 0);
				LCD_wrstring("Sending Data....");
				LCD_setcursor(2, 0);
				LCD_wrstring("S:    DATA:     ");

				// print the descriptive heading followed by the data
				if (test == TEST_STEPHILO)
				{
					xil_printf("\n\rHigh->Low Test Data\t\tAppx. Sample Interval: %d msec\n\r", frq_smple_interval);
				}
				else
				{
					xil_printf("\n\rLow->High Test Data\t\tAppx. Sample Interval: %d msec\n\r", frq_smple_interval);
				}
				
				// trigger the serial charter program)
				xil_printf("===STARTPLOT===\n");

				// start with the second sample.  The first sample is not representative of
				// the data.  This will pretty-up the graph a bit								
				for (smpl_idx = 1; smpl_idx < NUM_FRQ_SAMPLES; smpl_idx++)
				{
					u16 count;
					
					count = sample[smpl_idx];
					
					//ECE544 Students:
                    //Convert from count to 'volts'
					v = LIGHTSENSOR_Count2Volts(count);
					
					voltstostrng(v, s);
					xil_printf("%d\t%d\t%s\n\r", smpl_idx, count, s);
					
					LCD_setcursor(2, 2);
					LCD_wrstring("   ");
					LCD_setcursor(2, 2);
					LCD_putnum(smpl_idx, 10);
					LCD_setcursor(2, 11);
					LCD_wrstring("     ");
					LCD_setcursor(2, 11);
					LCD_putnum(count, 10);
				}
				
				// stop the serial charter program				
				xil_printf("===ENDPLOT===\n");
				
				NX3_writeleds(0x00);
				old_btnsw = btnsw;								
				next_test = TEST_INVALID;			
			}  // do the step test and dump data
			else
			{
				next_test = test;
			}
		} // Test 1 & 2 - Step response
		else if (test == TEST_CHARACTERIZE)  // Test 3 - Characterize Response
		{
			if (test != next_test)
			{				
				LCD_clrd();
				LCD_setcursor(1,0);
				LCD_wrstring("|CHAR|Press RBtn");
				LCD_setcursor(2,0);
				LCD_wrstring("LED OFF-Release ");
			}
			// start the test on the rising edge of the Rotary Encoder button press
			// the test will write the samples into the global "sample[]"
			// the samples will be sent to stdout when the Rotary Encoder button
			// is released
			if ((btnsw ^ old_btnsw) && (msk_BTN_ROT & btnsw))  // do the step test and dump data  
			{
				// light "Run" (rightmost) LED to show the test has begun
				// and do the test.  The test will return when the measured samples array
				// has been filled.  Turn off the rightmost LED after the data has been
				// captured to let the user know he/she can release the button
				NX3_writeleds(0x01);			
				DoTest_Characterize();
				NX3_writeleds(0x00);
				
				// wait for the Rotary Encoder button to be released
				// and then send the sample data to stdout
				do
				{
					NX3_readBtnSw(&btnsw);
					delay_msecs(10);
				} while ((btnsw & msk_BTN_ROT) == 0x80);
				
				// light "Transfer" LED to indicate that data is being transmitted
				// Show the traffic on the LCD
				NX3_writeleds(0x02);
				LCD_clrd();
				LCD_setcursor(1, 0);
				LCD_wrstring("Sending Data....");
				LCD_setcursor(2, 0);
				LCD_wrstring("S:    DATA:     ");

				xil_printf("\n\rCharacterization Test Data\t\tAppx. Sample Interval: %d msec\n\r", frq_smple_interval);

				// trigger the serial charter program)
				xil_printf("===STARTPLOT===\n\r");
				
				for (smpl_idx = STEPDC_MIN; smpl_idx <= STEPDC_MAX; smpl_idx++)
				{
					u16 		count;
					Xfloat32	v;
					char		s[10]; 
					
					count = sample[smpl_idx];
					
					//ECE544 Students:
                    //Convert from count to 'volts'
					v = LIGHTSENSOR_Count2Volts((Xuint32)count);
					
					voltstostrng(v, s);
					xil_printf("%d\t%d\t%s\n\r", smpl_idx, count, s);

					LCD_setcursor(2, 2);
					LCD_wrstring("   ");
					LCD_setcursor(2, 2);
					LCD_putnum(smpl_idx, 10);
					LCD_setcursor(2, 11);
					LCD_wrstring("     ");
					LCD_setcursor(2, 11);
					LCD_putnum(count, 10);
				}

				// stop the serial charter program				
				xil_printf("===ENDPLOT===\n\r");
				
				NX3_writeleds(0x00);
				old_btnsw = btnsw;								
				next_test = TEST_INVALID;
			}  // do the step test and dump data
			else
			{
				next_test = test;
			}
		} // Test 3 - Characterize Response
		else  // outside the current test range - blink LED's and hang
		{
			// should never get here but just in case
			NX3_writeleds(0xFF);
			delay_msecs(2000);
			NX3_writeleds(0x00);
		}
		// wait a bit and start again
		delay_msecs(100);			 								
	}  // while(1) loop
 }  // end main()
예제 #18
0
int main() {

	XStatus 		status;
	u16				sw, oldSw =0xFFFF;				// 0xFFFF is invalid --> makes sure the PWM freq is updated 1st time
	int				rotcnt, oldRotcnt = 0x1000;	
	bool			done = false;
	bool 			hw_switch = 0;
	
	init_platform();

	// initialize devices and set up interrupts, etc.

	status = do_init();
	
	if (status != XST_SUCCESS) 	{

		PMDIO_LCD_setcursor(1,0);
		PMDIO_LCD_wrstring("****** ERROR *******");
		PMDIO_LCD_setcursor(2,0);
		PMDIO_LCD_wrstring("INIT FAILED- EXITING");
		exit(XST_FAILURE);
	}
	
	// initialize the global variables

	timestamp = 0;							
	pwm_freq = INITIAL_FREQUENCY;
	pwm_duty = INITIAL_DUTY_CYCLE;
	clkfit = 0;
	new_perduty = false;
	
	// start the PWM timer and kick of the processing by enabling the Microblaze interrupt

	PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);	
	PWM_Start(&PWMTimerInst);
	microblaze_enable_interrupts();
	
	// display the greeting   

	PMDIO_LCD_setcursor(1,0);
	PMDIO_LCD_wrstring("ECE544 Project 1");
	PMDIO_LCD_setcursor(2,0);
	PMDIO_LCD_wrstring(" by Rehan Iqbal ");
	NX4IO_setLEDs(0x0000FFFF);
	delay_msecs(2000);
	NX4IO_setLEDs(0x00000000);
		
   // write the static text to the display

	PMDIO_LCD_clrd();
	PMDIO_LCD_setcursor(1,0);
	PMDIO_LCD_wrstring("G|FR:    DCY:  %");
	PMDIO_LCD_setcursor(2,0);
	PMDIO_LCD_wrstring("D|FR:    DCY:  %");

	// turn off the LEDs and clear the seven segment display

	NX4IO_setLEDs(0x00000000);
	NX410_SSEG_setAllDigits(SSEGLO, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE);
	NX410_SSEG_setAllDigits(SSEGHI, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE);
	  
	// main loop

	do	{ 
		
		// check rotary encoder pushbutton to see if it's time to quit
		
		if (PMDIO_ROT_isBtnPressed()) {
			done = true;
		}

		else {
			
			new_perduty = false;
			
			// get the switches and mask out all but the switches that determine the PWM timer frequency
			
			sw &= PWM_FREQ_MSK;
			sw = NX4IO_getSwitches();
			
			if (sw != oldSw) {	 
				
				// check the status of sw[2:0] and assign appropriate PWM output frequency

				switch (sw & 0x07) {
					
					case 0x00:	pwm_freq = PWM_FREQ_100HZ;	break;
					case 0x01:	pwm_freq = PWM_FREQ_1KHZ;	break;
					case 0x02:	pwm_freq = PWM_FREQ_10KHZ;	break;
					case 0x03:	pwm_freq = PWM_FREQ_50KHZ;	break;
					case 0x04:	pwm_freq = PWM_FREQ_100KHZ;	break;
					case 0x05:	pwm_freq = PWM_FREQ_500KHZ;	break;
					case 0x06:	pwm_freq = PWM_FREQ_1MHZ;	break;
					case 0x07:	pwm_freq = PWM_FREQ_5MHZ;	break;

				}
				
				// check the status of sw[3] and assign to global variable

				hw_switch = (sw & 0x08);

				// update global variable indicating there are new changes

				oldSw = sw;
				new_perduty = true;
			}
		
			// read rotary count and handle duty cycle changes
			// limit duty cycle to 0% to 99%
			
			PMDIO_ROT_readRotcnt(&rotcnt);

			if (rotcnt != oldRotcnt) {
				
				// show the rotary count in hex on the seven segment display
				
				NX4IO_SSEG_putU16Hex(SSEGLO, rotcnt);

				// change the duty cycle
				
				pwm_duty = MAX(1, MIN(rotcnt, 99));
				oldRotcnt = rotcnt;
				new_perduty = true;
			}

			// update generated frequency and duty cycle	
			
			if (new_perduty) {
				
				u32 			freq, 
								dutycycle;

				unsigned int 	detect_freq = 0x00;
				unsigned int 	detect_duty = 0x00;
			
				// set the new PWM parameters - PWM_SetParams stops the timer
				
				status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
				
				if (status == XST_SUCCESS) {
					
					PWM_GetParams(&PWMTimerInst, &freq, &dutycycle);

					update_lcd(freq, dutycycle, 1);

					// check if sw[3] is high or low (HWDET / SWDET)
					// pass functions different args depending on which mode is selected

					if (hw_switch) {

						detect_freq = calc_freq(hw_high_count, hw_low_count, hw_switch);
						detect_duty = calc_duty(hw_high_count, hw_low_count);
					}

					else {

						detect_freq = calc_freq(sw_high_count, sw_low_count, hw_switch);
						detect_duty = calc_duty(sw_high_count, sw_low_count);
					}

					// update the LCD display with detected frequency & duty cycle

					update_lcd(detect_freq, detect_duty, 2);
										
					PWM_Start(&PWMTimerInst);
				}
			}
		}

	} while (!done);
	
	// wait until rotary encoder button is released	

	do {
		delay_msecs(10);
	} while (PMDIO_ROT_isBtnPressed());

	// we're done,  say goodbye

	xil_printf("\nThat's All Folks!\n\n");
	
	PMDIO_LCD_setcursor(1,0);
	PMDIO_LCD_wrstring("That's All Folks");
	PMDIO_LCD_setcursor(2,0);
	PMDIO_LCD_wrstring("                ");
	
	NX410_SSEG_setAllDigits(SSEGHI, CC_BLANK, CC_B, CC_LCY, CC_E, DP_NONE);
	NX410_SSEG_setAllDigits(SSEGLO, CC_B, CC_LCY, CC_E, CC_BLANK, DP_NONE);

	delay_msecs(5000);

	// turn the lights out

	PMDIO_LCD_clrd();
	NX410_SSEG_setAllDigits(SSEGHI, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE);
	NX410_SSEG_setAllDigits(SSEGLO, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE);

	NX4IO_RGBLED_setDutyCycle(RGB1, 0, 0, 0);
	NX4IO_RGBLED_setChnlEn(RGB1, false, false, false);

	// exit gracefully

	cleanup_platform();

	exit(0);
}
예제 #19
0
/*****
 * DoTest_Characterize() - Perform the Characterization test
 *
 * This function starts the duty cycle at the minimum duty cycle and
 * then sweeps it to the max duty cycle for the test.
 * Samples are collected into the global array sample[].
 * The function toggles the TEST_RUNNING signal high for the duration
 * of the test as a debug aid and adjusts the global "pwm_duty"
 *
 * The test also sets the global frequency count min and max counts to
 * help limit the counts to the active range for the circuit
 *****/
XStatus DoTest_Characterize(void)
{
    XStatus		Status;					// Xilinx return status
    unsigned	tss;					// starting timestamp
    int		n;					// number of samples
    Xuint32         freq_max_cnt = 1000;

    int             i = 0;
    double diff = 0;


    // stabilize the PWM output (and thus the lamp intensity) at the
    // minimum before starting the test
    pwm_duty = STEPDC_MIN;
    Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
    if (Status == XST_SUCCESS)
    {
        PWM_Start(&PWMTimerInst);
    }
    else
    {
        return -1;
    }
    //Wait for the LED output to settle before starting
    delay_msecs(1500);

    // sweep the duty cycle from STEPDC_MIN to STEPDC_MAX
    smpl_idx = STEPDC_MIN;
    n = 0;
    tss = timestamp;
    while (smpl_idx <= STEPDC_MAX)
    {
        Status = PWM_SetParams(&PWMTimerInst, pwm_freq, smpl_idx);
        if (Status == XST_SUCCESS)
        {
            PWM_Start(&PWMTimerInst);
        }
        else
        {
            return -1;
        }

        sample[smpl_idx++] = LIGHTSENSOR_Capture(LIGHTSENSOR_BASEADDR, slope, offset, is_scaled, freq_min_cnt);

        n++;
        delay_msecs(50);
    }
    frq_smple_interval = (timestamp - tss) / smpl_idx;

    //Find min and max values to set scaling
    for (i = 1; i < STEPDC_MAX ; i++)
    {
        if (sample[i] < freq_min_cnt)
        {
            freq_min_cnt = sample[i];
        }
        if (sample[i] > freq_max_cnt)
        {
            freq_max_cnt = sample[i];
        }
    }

    // Send min and max to set scaling and calculate slope and offset
    diff = freq_max_cnt - freq_min_cnt;
    slope = 4095.0 / diff;

    is_scaled = true;
    return n;
}
/*****
 * DoTest_PID() - Perform PID control and it's derivitives
 * 
 * This function adjusts the global "pwm_duty", "offset" and gains (GP, GI, GD) values to try to 
 * bring the control system simulator close to the ADC setpoint.  The initial state of the PWM
 * is derived from the global "init_high" flag. NUM_ADC_SAMPLES are collected
 * into the global array sample[] and the count returned.  The function toggles the TEST_RUNNING
 * signal high for the duration of the test as a debug aid.  An approximate
 * ADC sample interval is written to the global variable "adc_smpl_interval"
 *
 * PID control provides finer control over the control input than that offered by Bang-bang control.
 * The biggest contributor to the control input is a value proportional to the distance between the
 * setpoint and the actual point.  Integral and Derivitive terms based on the history of the control
 * system are used to fine tune the control input.
 *
 * NOTE:  THIS ALGORIHM IS LEFT AS AN EXERCISE TO THE READER 
 *****/
int DoTest_PID(void)
{

	XStatus		Status;					// Xilinx return status
	unsigned	tss;					// starting timestamp
	u16		adc_1, adc_2;			// holds the ADC count - sampled twice and averaged
	u16		adc_cnt;				// ADC counts to display
	int			n;						// number of samples

	Xfloat32	integral, derivative;	// integral, derivative terms
	Xfloat32	error, prev_error;			// error and prev error terms
	Xfloat32	setpoint_volt, currentadc_volt;	// Setpoint and ADC count in volts

	//The initial state of the PWM is derived from the global "init_high" flag.
	if(init_high)
	  pwm_duty = PWM_STEPDC_MIN;
	else
	  pwm_duty = PWM_STEPDC_MAX;

	 // Get the PWM status
	 Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
	 if(Status == XST_SUCCESS)
	      PWM_Start(&PWMTimerInst);
	 else
	     return -1;

	 delay_msecs(1000);

	 integral = 0;
	 derivative = 0;
	 prev_error = 0;
	 smpl_idx = 0;
	 n = 0;
	 tss = timestamp;

	setpoint_volt = PmodCtlSys_ADCVolts(setpoint);

	while (smpl_idx <= NUM_ADC_SAMPLES)
	{
    	// sample ADC twice and average the readings
		adc_1=PmodCtlSys_readADC(&SPIInst);
		delay_msecs(1);
		adc_2=PmodCtlSys_readADC(&SPIInst);
		adc_cnt = (adc_1 + adc_2) / 2;

		currentadc_volt = PmodCtlSys_ADCVolts( adc_cnt + offset);

		// calculate error: Negate the value to avoid -ve PID control parameters
		error = currentadc_volt - setpoint_volt;
		derivative = error - prev_error;
		prev_error = error;
		if (abs(error) < setpoint_volt/10)
			integral += error;
		else
			integral = 0;

		pwm_duty = (int)((error*GP) + (integral *GI) + (derivative*GD));

		// Set the duty cycle based on the calculated value
		if (pwm_duty < PWM_STEPDC_MIN)
			pwm_duty = PWM_STEPDC_MIN;
		else if (pwm_duty > PWM_STEPDC_MAX)
			pwm_duty = PWM_STEPDC_MIN;

		Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
		if (Status == XST_SUCCESS)
		  	PWM_Start(&PWMTimerInst);
		else
		  	return -1;

		sample[smpl_idx++] = adc_cnt;
		n++;
		delay_msecs(5);
	}
	adc_smple_interval = (timestamp - tss) / smpl_idx;
	return n;
}
int main() {
	XStatus Status;
	u32 btnsw = 0x00000000, old_btnsw = 0x000000FF, diff_btnsw;
	u32 leds;
	int rotcnt, old_rotcnt;
	Test_t test;
	ParamSel_t param_select;

	bool wrlcd_dynamic;
	bool wrlcd_static;

	// initialize devices and set up interrupts, etc.
	Status = do_init();
	if (Status != XST_SUCCESS) {
		LCD_setcursor(1, 0);
		LCD_wrstring("****** ERROR *******");
		LCD_setcursor(2, 0);
		LCD_wrstring("INIT FAILED- EXITING");
		exit(XST_FAILURE);
	}

	// initialize the global variables
	timestamp = 0;
	pwm_freq = PWM_FREQUENCY_HZ;
	pwm_duty = PWM_STEPDC_MIN;

	// initialize the local variables
	btnsw = 0x00;
	old_btnsw = 0x00;
	rotcnt = 0;
	old_rotcnt = 0;
	param_select = SLCT_GP;
	wrlcd_dynamic = true;
	wrlcd_static = true;
	leds = LEDS_ALLOFF;
	_prev_button_down_count = 0;
	// Enable the Microblaze caches and
	// kick off the processing by enabling the Microblaze interrupt
	// this starts the FIT timer which updates the timestamp.
	if (USE_ICACHE == 1) {
		microblaze_invalidate_icache();
		microblaze_enable_icache();
	}
	if (USE_DCACHE == 1) {
		microblaze_invalidate_dcache();
		microblaze_enable_dcache();
	}
	microblaze_enable_interrupts();

	// display the greeting
	LCD_setcursor(1, 0);
	LCD_wrstring("ECE544 Project 2");
	LCD_setcursor(2, 0);
	LCD_wrstring("Starter App-R5.0");
	NX3_writeleds(LEDS_ALLON);
	delay_msecs(2000);
	NX3_writeleds(LEDS_ALLOFF);

	// Set the PWM and ADC min and max counts by forcing a characterization
	LCD_clrd();
	LCD_setcursor(1, 0);
	LCD_wrstring("Characterizing..");
	DoTest_Characterize();
	LCD_setcursor(2, 0);
	LCD_wrstring("...Done         ");

	//*****GAIN AND OFFSET ARE HARDWIRED IN THE STARTER APP *****
	// initialize the control parameters
	// start the set point in the middle of the range	
	setpoint = (ADC_max_cnt - ADC_min_cnt) / 2;
	offset = 100;
	GP = 10;
	GD = 5;
	GI = 5;
	init_high = false;
	//*****GAIN AND OFFSET ARE HARDWIRED IN THE STARTER APP *****


	// main loop - there is no exit except by hardware reset
	while (1) {
		// write static portion of output to display
		if (wrlcd_static) {
			LCD_clrd();
			LCD_setcursor(1, 0);
			LCD_wrstring("G|Pxxx Ixxx Dxxx");
			LCD_setcursor(2, 0);
			LCD_wrstring("SP:+x.xx OFF:xxx");
			wrlcd_static = false;
		}

		// write the dynamic portion of output to display
		if (wrlcd_dynamic) {
			Xfloat32 v;
			u16 count;
			char s[20];
			u32 row, col;

			// display GP, GI, and GD
			LCD_setcursor(1, 3);
			LCD_wrstring("   ");
			LCD_setcursor(1, 3);
			LCD_putnum(GP, 10);

			LCD_setcursor(1, 8);
			LCD_wrstring("   ");
			LCD_setcursor(1, 8);
			LCD_putnum(GI, 10);

			LCD_setcursor(1, 13);
			LCD_wrstring("   ");
			LCD_setcursor(1, 13);
			LCD_putnum(GD, 10);

			LCD_setcursor(2, 13);
			LCD_wrstring("   ");
			LCD_setcursor(2, 13);
			LCD_putnum(offset, 10);

			// display the setpoint in volts
			count = setpoint;
			v = PmodCtlSys_ADCVolts(count);
			voltstostrng(v, s);
			LCD_setcursor(2, 3);
			LCD_wrstring("     ");
			LCD_setcursor(2, 3);
			LCD_wrstring(s);

			// place the cursor under the currently selected parameter
			LCD_docmd(LCD_DISPLAYONOFF, LCD_CURSOR_OFF);
			switch (param_select) {
				case SLCT_OFFSET:
					row = 2;
					col = 13;
					break;
				case SLCT_GP:
					row = 1;
					col = 3;
					break;
				case SLCT_GD:
					row = 1;
					col = 13;
					break;
				case SLCT_GI:
					row = 1;
					col = 8;
					break;
				case SLCT_INVALID:
					break;
			}
			if (param_select != SLCT_INVALID) {
				LCD_setcursor(row, col);
				LCD_docmd(LCD_DISPLAYONOFF, LCD_CURSOR_ON);
			}
			wrlcd_dynamic = false;
		}

		// read switches and buttons to get the test to perform and its initial value
		// display the selected test on the LEDs   
		NX3_readBtnSw(&btnsw);
		init_high = (btnsw & SW_INIT_HILO) ? true : false;
		test = btnsw & SW_TEST_SELECT;

		//update the HI/LO and TEST LEDs
		leds &= ~(LEDS_HILO | LEDS_TEST);
		leds |= (init_high == true) ? LEDS_HILO : 0;
		leds |= test << 3;
		NX3_writeleds(leds);

		// read rotary count and handle setpoint changes
		// accelerate setpoint if speedup threshold has been exceeded
		// Use MIN and MAX to keep scaled ADC count within range
		ROT_readRotcnt(&rotcnt);
		if (rotcnt != old_rotcnt) {
			if (abs(rotcnt - old_rotcnt) > ROTCNT_SPEEDUP_GATE) {
				setpoint += (rotcnt - old_rotcnt) * ROTCNT_DELTA
						* ROTCNT_SPEEDUP_FACTOR;
			} else {
				setpoint += (rotcnt - old_rotcnt) * ROTCNT_DELTA;
			}
			setpoint = MAX(ADC_min_cnt, MIN(setpoint, ADC_max_cnt));
			old_rotcnt = rotcnt;
			wrlcd_dynamic = true;
		} // rotary count changed

		//***** NOTE:  User interface handling should go in this section.  *****
		//***** The starter app just lets the user select the setpoint and *****
		//***** run the test selected by the switches                      *****

		// look at the buttons and take action on the rising edge of a button press
		bool north_button = btnsw & msk_BTN_NORTH;
		bool east_button = btnsw & msk_BTN_EAST;
		bool west_button = btnsw & msk_BTN_WEST;
		bool button_down = north_button || east_button || west_button;

		if (button_down)
		{
			_prev_button_down_count++;
			if (_prev_button_down_count > 5)
				_prev_button_down_count = 5;

			if (north_button) {
				switch (param_select) {
					case SLCT_GP:
						param_select = SLCT_GI;
						break;
					case SLCT_GI:
						param_select = SLCT_GD;
						break;
					case SLCT_GD:
						param_select = SLCT_OFFSET;
						break;
					case SLCT_OFFSET:
						param_select = SLCT_GP;
						break;					
				}
				wrlcd_dynamic = true;
			}

			if (east_button) {
				switch (param_select) {
					case SLCT_GP:
						GP+=_prev_button_down_count;
						break;
					case SLCT_GI:
						GI+=_prev_button_down_count;
						break;
					case SLCT_GD:
						GD+=_prev_button_down_count;
						break;
					case SLCT_OFFSET:
						offset+=_prev_button_down_count;
						break;					
				}
				wrlcd_dynamic = true;
			}

			if (west_button) {
				switch (param_select) {
					case SLCT_GP:
						GP-=_prev_button_down_count;
						break;
					case SLCT_GI:
						GI-=_prev_button_down_count;
						break;			
					case SLCT_GD:
						GD-=_prev_button_down_count;
						break;
					case SLCT_OFFSET:
						offset-=_prev_button_down_count;
						break;					
				}
				wrlcd_dynamic = true;
			}
		} else {
			_prev_button_down_count = 0;
		}

		btnsw &= BTN_MSK_ALLBUTTONS;
		diff_btnsw = (btnsw ^ old_btnsw) & btnsw;
		old_btnsw = btnsw;

		if (diff_btnsw & BTN_RUN_XFER) // run a test
		{
			Xfloat32 vADC, vSP; // VADC from circuit and Vsetpoint
			char s1[20], s2[30]; // display and print strings
			int (*funcPtr)(void); // pointer to test function
			int n; // number of samples to transfer (returned by test functions)

			switch (test) // set up for the selected test
			{
				case TEST_BB: // Bit Bang control
					strcpy(s1, "|BB  |Press RBtn");
					strcpy(s2, "Bit Bang Control Test Data");
					funcPtr = DoTest_BB;
					break;
				case TEST_PID: // PID control
					strcpy(s1, "|PID |Press RBtn");
					strcpy(s2, "PID Control Test Data");
					funcPtr = DoTest_PID;
					break;
				case TEST_CHARACTERIZE: // characterize control system simulator
					strcpy(s1, "|CHAR|Press RBtn");
					strcpy(s2, "Characterization Test Data");
					funcPtr = DoTest_Characterize;
					break;
				default: // no test to run
					strcpy(s1, "");
					strcpy(s2, "");
					funcPtr = NULL;
					break;
			}

			// Change the display to indicate that a test will be run			
			LCD_clrd();
			LCD_setcursor(1, 0);
			LCD_wrstring(s1);
			LCD_setcursor(2, 0);
			LCD_wrstring("LED OFF-Release ");

			// turn on Run LED to show the test has begun
			// and do the test.  The test will return when the ADC samples array
			// has been filled.  Turn off the rightmost LED after the data has been 
			// captured to let the user know he/she can release the button
			if (funcPtr != NULL) {
				leds |= LEDS_RUN;
				NX3_writeleds(leds);
				n = funcPtr();
				leds &= ~LEDS_RUN;
				NX3_writeleds(leds);
				// wait for the Rotary Encoder button to be released
				// and then send the sample data to stdout
				do {
					NX3_readBtnSw(&btnsw);
					delay_msecs(10);
				} while (btnsw & BTN_RUN_XFER);

				// turn on Transfer LED to indicate that data is being transmitted
				// Show the transfer  traffic on the LCD
				leds |= LEDS_XFER;
				NX3_writeleds(leds);
				LCD_clrd();
				LCD_setcursor(1, 0);
				LCD_wrstring("Sending Data....");
				LCD_setcursor(2, 0);
				LCD_wrstring("S:    DATA:     ");

				// transfer the descriptive heading followed by the data	
				xil_printf("\n\r%s\tAppx. Sample Interval: %d msec\n\r", s2,
						adc_smple_interval);
				xil_printf("sample\tADCCount\tVout\tsetpoint\tPWMCount\n\r");

				// tell SerialCharter to start gathering data)
				xil_printf("===STARTPLOT===\n");

				for (smpl_idx = 2; smpl_idx < n; smpl_idx++) {
					u16 count;

					count = sample[smpl_idx];
					vADC = PmodCtlSys_ADCVolts(count);
					vSP = PmodCtlSys_ADCVolts(setpoint);
					voltstostrng(vADC, s1);
					voltstostrng(vSP, s2);
					xil_printf("%d\t%d\t%s\t%s\t%d\n\r", smpl_idx, count, s1,
							s2, PIDdebug[smpl_idx].pwm_count);
					LCD_setcursor(2, 2);
					LCD_wrstring("   ");
					LCD_setcursor(2, 2);
					LCD_putnum(smpl_idx, 10);
					LCD_setcursor(2, 11);
					LCD_wrstring("     ");
					LCD_setcursor(2, 11);
					LCD_putnum(count, 10);
				}

				// tell SeriaCharter to stop gathering data and display the graph			
				xil_printf("===ENDPLOT===\n");

				// transfer complete - turn Transfer LED off and wrap up command processing
				leds &= ~LEDS_XFER;
				NX3_writeleds(leds);
				wrlcd_static = true;
				wrlcd_dynamic = true;
			}
		} // run a test

		// wait a bit and start again
		delay_msecs(100);
	} // while(1) loop
} // end main()
예제 #22
0
/*****
 * DoTest_Characterize() - Perform the Characterization test
 * 
 * This function starts the duty cycle at the minimum duty cycle and
 * then sweeps it to the max duty cycle for the test.
 * Samples are collected into the global array sample[].  
 * The function toggles the TEST_RUNNING signal high for the duration
 * of the test as a debug aid and adjusts the global "pwm_duty"
 *
 * The test also sets the global frequency count min and max counts to
 * help limit the counts to the active range for the circuit
 *****/
XStatus DoTest_Characterize(void)
{
	XStatus		Status;					// Xilinx return status
	unsigned	tss;					// starting timestamp
	volatile u16	frq_cnt;				// counts to display
	int			n;						// number of samples
	Xuint32		freq, dutyfactor;		// current frequency and duty factor
    Xuint32         freq_max_cnt = 3000;
    Xuint32         freq_min_cnt = 3000;
    int i;
    double diff = 0;


	// stabilize the PWM output (and thus the lamp intensity) at the
	// minimum before starting the test
	pwm_duty = STEPDC_MIN;
	Status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty);
	if (Status == XST_SUCCESS)
	{							
		PWM_Start(&PWMTimerInst);
	}
	else
	{
		return -1;
	}
	//Wait for the LED output to settle before starting
    delay_msecs(1500);
		
	// sweep the duty cycle from STEPDC_MIN to STEPDC_MAX
	smpl_idx = STEPDC_MIN;
	n = 0;
	tss = timestamp;
	while (smpl_idx <= STEPDC_MAX)
	{
		Status = PWM_SetParams(&PWMTimerInst, pwm_freq, smpl_idx);
		if (Status == XST_SUCCESS)
		{							
			PWM_Start(&PWMTimerInst);
		}
		else
		{
			return -1;
		}
		
        //ECE544 Students:
        // make the light sensor measurement
		//frq_cnt = LIGHTSENSOR_mReadPERIOD(LIGHTSENSOR_BASEADDR);
		frq_cnt = LIGHTSENSOR_Capture(LIGHTSENSOR_BASEADDR, slope, offset, is_scaled);
		sample[smpl_idx++] = frq_cnt;
		

		n++;
		delay_msecs(50);
	}		
	frq_smple_interval = (timestamp - tss) / smpl_idx;

    //ECE544 Students:
    //Find the min and max values and set the scaling/offset factors to use for your convert to 'voltage' function.
    //NOTE: It may also be useful to scale the actual 'count' values to a range of 0 - 4095 for the SerialCharter application to work correctly 
	for (i = 0; i < STEPDC_MAX ; i++)
	    {
	        if (sample[i] < freq_min_cnt)
	        {
	            freq_min_cnt = sample[i];
	        }
	        if (sample[i] > freq_max_cnt)
	        {
	            freq_max_cnt = sample[i];
	        }
	    }
	// YOUR_FUNCTION(FRQ_min_cnt,FRQ_max_cnt);
	//LIGHTSENSOR_SetScaling(freq_max_cnt, freq_min_cnt, &slope, &offset);
	diff = freq_max_cnt - freq_min_cnt;
	slope = 4095.0 / diff;
	offset = freq_min_cnt;
	

	is_scaled = true;
    return n;
}