Exemplo n.º 1
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;
}
/*****
 * 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;
}
Exemplo n.º 3
0
void init_feedback_system(void) {

   // Calibrating the sensor
   PWM_SetParams(&instPWMTimer, PWM_FREQ_005KHZ, 0);
   MB_Sleep(2000);
   TSL235R_SetMinThreshold((void*) XPAR_TSL235R_0_S00_AXI_BASEADDR);

   PWM_SetParams(&instPWMTimer, PWM_FREQ_005KHZ, 99);
   MB_Sleep(2000);
   TSL235R_SetMaxThreshold((void*) XPAR_TSL235R_0_S00_AXI_BASEADDR);

   // Putting PWM in a know state before returning
   PWM_SetParams(&instPWMTimer, PWM_FREQ_005KHZ, 0);
}
Exemplo n.º 4
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;
}
/*****
 * 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;
}
Exemplo n.º 6
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);
 }
/*****
 * 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;
}
/*****
 * 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;
}
/*****
 * 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;

}
Exemplo n.º 10
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);
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
int main () {
   XStatus status;
   // VARS : to hold user input stuff
   int      encoderCurn = 0x0000;
   int      encoderPrev = 0x1000;   
   int      PWMDutyGen = 50;
   bool     PWMGenUpdateFlag = false;
   u32      PWMFreqGenRead;
   u32      PWMDutyGenRead;

   /*u32      tsl235rHiTimePrev = 0;*/
   /*int      PWMCycTime;*/
   /*int      PWMFreqMeas;*/

   int      tsl235rFreqPrev = 0;


   // Initializations
   init_platform();
   status = init_axi_devices();
   if (status != XST_SUCCESS) errorExit();
   init_welcom();


   // SET : PWM generator begin, enable microblaze interrupts
   /*PWM_SetParams(&instPWMTimer, PWM_FREQ_005KHZ, PWMDutyGen);   */
   PWM_Start(&instPWMTimer);
   microblaze_enable_interrupts();

   init_feedback_system();
   
   while(1) {
      PWMGenUpdateFlag = false;

      // CHECK : Updates on ENCODER
      PMDIO_ROT_readRotcnt(&encoderCurn);
      if (encoderCurn != encoderPrev) {

         // SET seven-seg with encoder value
         NX4IO_SSEG_putU16Hex(SSEGLO, encoderCurn);

         PWMDutyGen = MAX(0, MIN(encoderCurn, 99));
         encoderPrev = encoderCurn;
         PWMGenUpdateFlag = true;
      }

      // SET : Update PWM Generator
      if (PWMGenUpdateFlag) {

         // set the new PWM parameters - PWM_SetParams stops the timer
         status = PWM_SetParams(&instPWMTimer, PWM_FREQ_005KHZ, PWMDutyGen);
         if (status != XST_SUCCESS) errorExit();

         // GET : read the PWM parameters back from the PWM generator
         PWM_GetParams(&instPWMTimer, &PWMFreqGenRead, &PWMDutyGenRead);
         update_lcd(PWMFreqGenRead, PWMDutyGenRead, 1);
         PWM_Start(&instPWMTimer);
      }

      /*if (tsl235rHiTimePrev != tsl235rHiTime) {*/
         /*PWMCycTime = (int) tsl235rHiTime * 2;*/
         /*PWMFreqMeas = 100000000 / PWMCycTime;*/
         /*update_lcd(PWMFreqMeas, 0, 2);*/

         /*tsl235rHiTimePrev = tsl235rHiTime;*/
      /*}*/
      if (tsl235rFreqPrev != tsl235rFreq) {
         update_lcd(tsl235rFreq, 50, 2);

         tsl235rFreq = tsl235rFreqPrev;
      }

   }
   
}