コード例 #1
0
void UpdateSpeed_ISR(){
	 uint32_t status = TimerIntStatus(WTIMER4_BASE,true);
	  TimerIntClear(WTIMER4_BASE,status);


	if(Target_Dir !=0){
		Direction_Dir=QEIDirectionGet(QEI0_BASE);
		EncoderDirVel=( (QEIVelocityGet(QEI0_BASE)*13)/48*12) * Direction_Dir;
		Error_Dir = Target_Dir - EncoderDirVel;
		I_Dir =  (I_Dir+Error_Dir) * Ki_Dir;
		D_Dir = D_Dir * (Error_Dir - LastError_Dir);
		PID_Dir = P_Dir + I_Dir + D_Dir;
		if(PID_Dir > 1022)
			PID_Dir = 1022;
		else if(PID_Dir < -1022)
			PID_Dir = -1022;
	}
	else{
		PID_Dir = 0;
		I_Dir=0;
		Error_Dir=0;
	}

	if(Target_Esq !=0){
		Direction_Esq=QEIDirectionGet(QEI1_BASE);
		EncoderEsqVel=( (QEIVelocityGet(QEI1_BASE)*13)/48*12) *  Direction_Esq;
		Error_Esq = Target_Esq - EncoderEsqVel;
		I_Esq =  (I_Esq+Error_Esq) * Ki_Esq;
		D_Esq = D_Esq * (Error_Esq - LastError_Esq);
		PID_Esq = P_Esq + I_Esq + D_Esq ;
		if(PID_Esq > 1022)
			PID_Esq = 1022;
		else if(PID_Esq < -1022)
			PID_Esq = -1022;
	}
	else{
		PID_Esq = 0;
		I_Esq=0;
		Error_Esq=0;
	}

	DRV8833_MotorB(PID_Dir);
	DRV8833_MotorA(PID_Esq);

	LastError_Dir = Error_Dir;
	LastError_Esq = Error_Esq;
}
コード例 #2
0
ファイル: encoder.c プロジェクト: shadowpho/Chalk-Bot
// * enc_vel_get **************************************************************
// * Returns the signed velocity of the encoder, in units of encoder pulses.  *
// * NOTE: If a change in the direction of rotation occured during the last   *
// *       velocity sampling period, this value will reflect the magnitude    *
// *       of displacement and it's sign will refer to the direction of       *
// *       encoder rotation at the end of the sampling period.                *
// *                                                                          *
// *       This yields undesirable results during direction changes, which    *
// *       may be unacceptable in your application. If this is the case,      *
// *       you should do your own first derivative calculation by sampling    *
// *       encoder position on a known timebase, and finding the delta from   *
// *       the previous sample.                                               *
// * encoder should be ENC_1 or ENC_2.                                        *
// ****************************************************************************
signed long enc_vel_get(unsigned char encoder)
{
  signed long retval;                                       // holds value to be returned
  if(encoder == ENC_1)
  {
    retval = (signed long)QEIVelocityGet(ENC_1_BASE);       // return encoder 1 reading
    retval *= QEIDirectionGet(ENC_1_BASE);                  // returns direction as -1 or +1
  }
  else if(encoder == ENC_2)
  {
    retval = (signed long)QEIVelocityGet(ENC_2_BASE);       // return encoder 2 reading
    retval *= QEIDirectionGet(ENC_2_BASE);                  // returns direction as -1 or +1    
 }
  else
  {
    retval = 0;                                             // return for invalid encoder ID
  }
  return retval;                                            // return the encoder position
}
コード例 #3
0
int main(void)
{
    long dir;
    unsigned long vel, pos;



    //
    // Set the clocking to run directly from the crystal.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);



    //
    // Set up low level I/O for printf()
    //
    llio_init(115200);


    //
    // Set up GPIO for LED
    //
    LED_INIT();



    //
    // Set up QEI peripheral
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

    GPIOPinTypeQEI(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_6);
    QEIConfigure(QEI0_BASE, (QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET |
                QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP), 0xffffffff);
    QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, SysCtlClockGet() / 10);

    QEIEnable(QEI0_BASE);
    QEIVelocityEnable(QEI0_BASE);



    //
    // Set up GPIO for encoder push switch
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_5);
    GPIOPadConfigSet(GPIO_PORTC_BASE, GPIO_PIN_5, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_5, GPIO_FALLING_EDGE);
    GPIOPortIntRegister(GPIO_PORTC_BASE, SW_IntHandler);
    GPIOPinIntEnable(GPIO_PORTC_BASE, GPIO_PIN_5);




    //
    // Set up the period for the SysTick timer.
    //
    SysTickPeriodSet(SysCtlClockGet() / 10);   // 10Hz SysTick timer


    //
    // Enable the SysTick Interrupt.
    //
    SysTickIntEnable();
    SysTickIntRegister(SysTickIntHandler);

    //
    // Enable SysTick.
    //
    SysTickEnable();

    printf("\r\nEncoder example\r\n");


    //
    // Loop forever.
    //
    while(1)
    {
        SysCtlSleep();              // sleep here till interrupt

        LED_TOGGLE();

        dir = QEIDirectionGet(QEI0_BASE);
        vel = QEIVelocityGet(QEI0_BASE);
        pos = QEIPositionGet(QEI0_BASE);
        printf("%d,%d,%d\r\n", dir, vel, pos);
    }
}
コード例 #4
0
ファイル: moteur.c プロジェクト: francisvalois/design3
// Asservissement en vitesse des moteurs pour qu'il atteignent leur propre consigne
void asservirMoteurs(void){
	pos0 = position_m3; //pas inversé
	pos1 = pos1 + QEIVelocityGet(QEI1_BASE)*QEIDirectionGet(QEI1_BASE); //pas inversé
	pos2 = position_m2;//pas inversé
	pos3 =  pos3 - QEIVelocityGet(QEI0_BASE)*QEIDirectionGet(QEI0_BASE); //inversé
	
	ajustementVitesse();
	
	//Motor 0
	measured_speed0 =  (pos0 - previous_pos0)/dt;
	if(measured_speed0 < 0){
		measured_speed0 = -measured_speed0;
	}
	previous_pos0 = pos0;
	if(consigne0 > 3200){
		output0 = PIDHandler0(&consigne0, &measured_speed0, &I0, &previous_error0, dt);
	}
	else{
		output0 = SlowPIDHandler0(&consigne0, &measured_speed0, &I0, &previous_error0, dt);
	}
	//Motor 1
	measured_speed1 = QEIVelocityGet(QEI1_BASE)/dt;//(pos1 - previous_pos1)*10;
	if(measured_speed1 < 0){
		measured_speed1 = -measured_speed1;
	}
	previous_pos1 = pos1;
	if(consigne1 > 3200){
		output1 = PIDHandler1(&consigne1, &measured_speed1, &I1, &previous_error1, dt);
	}
	else{
		output1 = SlowPIDHandler1(&consigne1, &measured_speed1, &I1, &previous_error1, dt);
	}
	//Motor 2
	measured_speed2 = (pos2 - previous_pos2)/dt;
	if(measured_speed2 < 0){
		measured_speed2 = -measured_speed2;
	}
	previous_pos2 = pos2;
	if(consigne2 > 3200){
		output2 = PIDHandler2(&consigne2, &measured_speed2, &I2, &previous_error2, dt);
	}
	else{
		output2 = SlowPIDHandler2(&consigne2, &measured_speed2, &I2, &previous_error2, dt);
	}
	//Motor 3
	measured_speed3 = QEIVelocityGet(QEI0_BASE)/dt;//(pos3 - previous_pos3)*10;
	if(measured_speed3 < 0){
		measured_speed3 = -measured_speed3;
	}
	previous_pos3 = pos3;
	if(consigne3 > 3200){
		output3 = PIDHandler3(&consigne3, &measured_speed3, &I3, &previous_error3, dt);
	}
	else{
		output3 = SlowPIDHandler3(&consigne3, &measured_speed3, &I3, &previous_error3, dt);
	}
	
	/*output0 = output0_old +(dt/Tf0)*(output0-output0_old);
	output1 = output1_old +(dt/Tf1)*(output1-output1_old);
	output2 = output2_old +(dt/Tf2)*(output2-output2_old);
	output3 = output3_old +(dt/Tf3)*(output3-output3_old);
	output0_old = output0;
	output1_old = output1;
	output2_old = output2;
	output3_old = output3;*/
	
	//output0_table[index%10] = output0;
	//output1_table[index%10] = output1;
	//output2_table[index%10] = output2;
	//output3_table[index%10] = output3;

	
	//Traduction 6400e de tour fraction appliqué au pulse width
	float fraction0;
	float fraction1;
	float fraction2;
	float fraction3;
	//Une équation linéaire est utilisée x*0.5/7700 = % du duty cycle
	fraction0 = ((output0*0.5)/7700);
	if(fraction0 > 0.99){
		fraction0 = 0.99;
	}
	else if(fraction0 < 0){
		fraction0 = 0;
	}
	fraction1 = ((output1*0.5)/7700);
	if(fraction1 > 0.99){
		fraction1 = 0.99;
	}else if(fraction1 < 0){
		fraction1 = 0;
	}
	fraction2 = ((output2*0.5)/7700);
	if(fraction2 > 0.99){
		fraction2 = 0.99;
	}else if(fraction2 < 0){
		fraction2 = 0;
	}
	fraction3 = ((output3*0.5)/7700);
	if(fraction3 > 0.99){
		fraction3 = 0.99;
	}else if(fraction3 < 0){
		fraction3 = 0;
	}
	PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, (periodPWM*fraction0));
	PWMPulseWidthSet(PWM_BASE, PWM_OUT_1, (periodPWM*fraction1));
	PWMPulseWidthSet(PWM_BASE, PWM_OUT_2, (periodPWM*fraction2));
	PWMPulseWidthSet(PWM_BASE, PWM_OUT_3, (periodPWM*fraction3));
	
	pos0_table[index%300]=GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
	pos1_table[index%300]=GPIOPinRead(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
	pos2_table[index%300]=pos2;
	pos3_table[index%300]=pos3;
	speed0_table[index%300]=measured_speed0;
	speed1_table[index%300]=measured_speed1;
	speed2_table[index%300]=measured_speed2;
	speed3_table[index%300]=measured_speed3;
	output0_table[index%300]=output0;
	output1_table[index%300]=output1;
	output2_table[index%300]=output2;
	output3_table[index%300]=output3;
	fraction0_table[index%300]=fraction0;
	fraction1_table[index%300]=fraction1;
	fraction2_table[index%300]=fraction2;
	fraction3_table[index%300]=fraction3;
	
	//Si le robot est immobile
	if(a_atteint_consigne && measured_speed0==0 && measured_speed1==0 && measured_speed2==0 && measured_speed3==0){
		resetVariables();
		resetQEIs();
		ROM_PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, 0);//periodPWM / 4);
		ROM_PWMPulseWidthSet(PWM_BASE, PWM_OUT_1, 0);
		ROM_PWMPulseWidthSet(PWM_BASE, PWM_OUT_2, 0);
		ROM_PWMPulseWidthSet(PWM_BASE, PWM_OUT_3, 0);
		est_en_mouvement = false;
	}
	else{
		est_en_mouvement = true;
	}
}
コード例 #5
0
//*****************************************************************************
//
// Handles the QEI velocity interrupt.
//
// This function is called when the QEI velocity timer expires.  If using the
// edge counting mode for rotor speed determination, the number of edges
// counted during the last velocity period is used as a measure of the rotor
// speed.
//
// \return None.
//
//*****************************************************************************
void
QEIIntHandler(void)
{
    unsigned long ulPrev, ulCount;

    //
    // Clear the QEI interrupt.
    //
    QEIIntClear(QEI0_BASE, QEI_INTTIMER);

    //
    // Increment the accumulated time to extend the range of the QEI timer,
    // which is used by the edge timing mode.
    //
    g_ulSpeedTime += SYSTEM_CLOCK / QEI_INT_RATE;

    //
    // See if edge counting mode is enabled.
    //
    if(HWREGBITW(&g_ulSpeedFlags, FLAG_COUNT_BIT) == 0)
    {
        //
        // Edge timing mode is currenting operating, so see if an edge was seen
        // during this QEI timing period.
        //
        if(HWREGBITW(&g_ulSpeedFlags, FLAG_EDGE_BIT) == 0)
        {
            //
            // No edge was seen, so set the rotor speed to zero.
            //
            g_ulRotorSpeed = 0;

            //
            // Since the amount of time the rotor is stopped is indeterminate,
            // skip the first edge when the rotor starts rotating again.
            //
            HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 1;
        }
        else
        {
            //
            // An edge was seen, so clear the flag so the next period can be
            // checked as well, and restart the edge reset counter.
            //
            HWREGBITW(&g_ulSpeedFlags, FLAG_EDGE_BIT) = 0;
        }

        //
        // There is nothing further to do.
        //
        return;
    }

    //
    // Get the number of edges during the most recent period.
    //
    ulCount = QEIVelocityGet(QEI0_BASE);

    //
    // Get the count of edges in the previous timing period.
    //
    ulPrev = g_ulSpeedPrevious;

    //
    // Save the count of edges during this timing period.
    //
    g_ulSpeedPrevious = ulCount;

    //
    // See if this timing period should be skipped.
    //
    if(HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT))
    {
        //
        // This timing period should be skipped, but an edge count from a
        // previous timing period now exists so the next timing period should
        // not be skipped.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 0;

        //
        // There is nothing further to be done.
        //
        return;
    }

    //
    // Average the edge count for the previous two timing periods.
    //
    ulCount = (ulPrev + ulCount) / 2;

    //
    // Compute the new speed from the number of edges.  Note that both
    // edges are counted by the QEI block, so the count for a full revolution
    // is double the number of encoder lines.
    //
    SpeedNewValue((ulCount * QEI_INT_RATE * 30) /
                  (UI_PARAM_NUM_LINES + 1));

    //
    // See if the number of edges has become too small, meaning that the edge
    // time has become large enough.
    //
    if(ulCount < (((MAX_EDGE_COUNT - EDGE_DELTA) * 2) / QEI_INT_RATE))
    {
        //
        // Edge timing mode should be used instead of edge counting mode.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_COUNT_BIT) = 0;

        //
        // Indicate that the first edge should be skipped in edge timing mode.
        //
        HWREGBITW(&g_ulSpeedFlags, FLAG_SKIP_BIT) = 1;

        //
        // Enable the GPIO interrupt to enable edge timing mode.
        //
        IntEnable(INT_GPIOC);
    }
}