Пример #1
0
/**
 * Run all tests
 */
int
umain (void) {


    isActivated = false;
    isForward = true;
    MagnetInit();
    PIDInit();
    uint8_t num_low_readings = 0;
    activateRun();

    while(1){

        //Read Magnet data
        ComputeMagnetTarget();

        //uint8_t oldForward = isForward;

        if (fangle > 90 || fangle < -90) {
            isForward = false;
        } else {
            isForward = true;
        }

        //Determine if we should change from activated->deactivated or vice versa
        if (isActivated) {
            if (FieldStrength < DEACTIVATE_THRESH) {
                num_low_readings++;
                //Need START_RAMPDOWN readings to begin motor rampdown
                if (num_low_readings > START_RAMPDOWN) {
                    SetTargetVelocity(TARGET_VELOCITY*(1.0-(float)(num_low_readings-START_RAMPDOWN)/(float)(DEACTIVATE_SAMPLES-START_RAMPDOWN)));
                    //SetTargetVelocity(TARGET_VELOCITY);
                }
                //If you have DEACTIVATE_SAMPLES low readings, deactivate
                if (num_low_readings == DEACTIVATE_SAMPLES) {
                    isActivated = false;
                    num_low_readings = 0;
                    SetTargetVelocity(TARGET_VELOCITY);
                    printf("\nDEACTIVATED");
                }
            } else {
                //We had a good reading, reset bad reading count and motor velocity
                num_low_readings = 0;
                SetTargetVelocity(TARGET_VELOCITY);
            }
        } else {
            //Activate on a single high reading
            if (FieldStrength > ACTIVATE_THRESH) {
                isActivated = true;
                SetTargetVelocity(TARGET_VELOCITY);
                printf("\nACTIVATED");
                PIDReset();
            }
        }

        SetTargetVelocity(NearbyScale*TargetVelocity);

        //Stop if not activated, otherwise update PID
        if (!isActivated) {
            CoastMotors();
            //pause(100);
        } else {
            PIDUpdate();
        }

        //pause(100);

    }

    return 0;

}
Пример #2
0
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////    MAIN    ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int main(void)
{
	IntMasterDisable();

	//=====SYSTEM PERIPHERAL INITIALIZATION=====

	// Initialize real time clock
	mRTCInit(RTC_RATE_HZ);

	// Millisecond timekeeping variable
	int time;

	//Add periodic tasks to be executed by systick
	mRTCAddTask(heightSample, HEIGHT_SAMPLE_RATE_HZ);

	// Set up display
    mDisplayInit(1000000);
    mDisplayLine("     Waiting...    ", 0, 5, 15);

	// Set up buttons
    ButtonInit();

	// Set up PWM
	mPWMInit();
	mPWMEnable(PWM4, false); // tail rotor, yaw control.
	mPWMEnable(PWM1, false); // main rotor, height control.

	//=========CONTROL INITIALIZATION========


	//-----altitude PID control------

    // Initialize altitude module
	heightInit();

	// =========PID parameters========================

	//Phils
	float H_kp = 1;float H_ki = 1.5;float H_kd = -0.5;

	short heightPIDOffset = 40;

	float Y_kp = 0.6;float Y_ki = 0;float Y_kd = 0;

	short YawPIDOffset = 0;//50;


	// Windup regulator
	float H_windup_limit = 10;
	if (H_ki)
		H_windup_limit /= H_ki;

	// height PID controller
	pid_t heightPID;
	PIDInit(&heightPID);
	PIDSet(&heightPID, H_kp, H_ki, H_kd, H_windup_limit); // set PID constants

	// height PID control variables
	//35; // PID out offset such that the rotor is at near-takoff speed
	short height = 0;
    short heightSetpoint = 0; // in degrees
    short heightError = 0;
    short heightPIDOut = 0;


	//-----yaw PID control-------

	// Initialise Yaw decoder module
	yawInit(); // yaw monitor



	float Y_windup_limit = 20; // Maximum integral contribution to PID output value
	if (Y_ki)
		Y_windup_limit /= Y_ki;	// devide by Y_ki to find maximum value in terms of error

	// Yaw PID controller
	pid_t yawPID;
	PIDInit(&yawPID);
	PIDSet(&yawPID, Y_kp, Y_ki, Y_kd, Y_windup_limit); // set PID constants

	// yaw PID control variables
	short yaw = 0;
	short yawSetpoint = 0;
    short yawError = 0;
    short yawPIDOut = 0;


    //
    // Enable interrupts to the processor.
    IntMasterEnable();


    short takeOffFlag = false;
	while (!takeOffFlag)
	{
		if (ButtonCheck(SELECT))
		//if (GPIOPinRead(GPIO_PORTG_BASE, 0x80))
		{
			takeOffFlag = true;
		}
	}

	// Reset setpoints to current position
	heightSetpoint = heightGet();
	yawSetpoint = yawGetAngle();



	mPWMEnable(PWM4, true); // tail rotor, yaw control.
	mPWMEnable(PWM1, true); // main rotor, height control.


	//spin up routine
	//spinUp(heightPIDOffset, yawPID);

	// Reset clock to zero for effective helicopter launch time
	mRTCSet(0);

	while (1)
	{
		//mDisplayClear();

		time = mRTCGetMilliSeconds();

		// Update Setpoints
		updateSetpoints(&yawSetpoint, &heightSetpoint);

		// ==================PID Control=================
		if ((time % (RTC_RATE_HZ/PID_RATE_HZ)) /*1000/(float)PID_RATE_HZ*/ == 0)
		{
			//
			// ~~~~~~~~~~~~~~~~~ HEIGHT PID ~~~~~~~~~~~~~~~~

			height = heightGet();

			heightError = heightSetpoint - height;

			heightPIDOut = PIDUpdate(&heightPID, heightError, 1.00 / (float)PID_RATE_HZ) + heightPIDOffset;

			if (heightPIDOut > 79)
				//heightPIDOut = 79;
			if (heightPIDOut < 2)
				heightPIDOut = 2;

			mPWMSet(PWM1, (unsigned short)heightPIDOut);


			//
			// ~~~~~~~~~~~~~~~~~~ YAW PID ~~~~~~~~~~~~~~~~~~~
			yaw = yawGetAngle();

			yawError = yaw - yawSetpoint;

			yawPIDOut = PIDUpdate(&yawPID, yawError, 1.00 / (float)PID_RATE_HZ) + YawPIDOffset;

			if (yawPIDOut > 79)
				yawPIDOut = 79;
			if (yawPIDOut < 2)
				yawPIDOut = 2;

			mPWMSet(PWM4, (unsigned short)yawPIDOut);

			// ===============================================
		}

		// RTC_RATE_HZ - PID_RATE_HZ
		if (( (time) % 10) == 0)
		{
			mDisplayLine("time:%.6d mS", time, 0, 7);
			mDisplayLine("Yaw  = %.4d'    ", (int)yaw, 1, 15);
			mDisplayLine("YSet = %.4d'    ", (int)yawSetpoint, 2, 15);
			mDisplayLine("YErr = %.4d'    ", (int)yawError, 3, 15);
			mDisplayLine("YOut = %.4d'    ", (int)yawPIDOut, 4, 15);
			mDisplayLine("height = ~%.3d ", (int)height, 5, 15);
			mDisplayLine("Hset   = %.4d   ", (int)heightSetpoint, 6, 15);
			mDisplayLine("Herr   = %.4d   ", (int)heightError, 7, 15);
			mDisplayLine("Hout   = %.4d   ", (int)heightPIDOut, 8, 15);
		}

		// should put this as part of the main while loop condition
		//if (ButtonCheck(SELECT))
		//{
		//	spinDown();
		//}

	}
}
Пример #3
0
int main(int argc, char **argv)
{
	//Register signal and signal handler
	signal(SIGINT, signal_callback_handler);
	
	//Init UDP with callbacks and pointer to run status
	initUDP( &UDP_Command_Handler, &UDP_Control_Handler, &Running );
	
	print("Eddie starting...\r\n");

	initIdentity();
	
	double EncoderPos[2] = {0};
	
	initEncoders( 183, 46, 45, 44 );
	print("Encoders activated.\r\n");

	imuinit();
	print("IMU Started.\r\n");

	float kalmanAngle;
	InitKalman();
	
#ifndef DISABLE_MOTORS
	print( "Starting motor driver (and resetting wireless) please be patient..\r\n" );
	if ( motor_driver_enable() < 1 )
		{
			print("Startup Failed; Error starting motor driver.\r\n");
			motor_driver_disable();
			return -1;
		}
	print("Motor Driver Started.\r\n");
#endif
	
	print("Eddie is starting the UDP network thread..\r\n");
	pthread_create( &udplistenerThread, NULL, &udplistener_Thread, NULL );
	
	print( "Eddie is Starting PID controllers\r\n" );
	/*Set default PID values and init pitchPID controllers*/
	pidP_P_GAIN = PIDP_P_GAIN;	pidP_I_GAIN = PIDP_I_GAIN;	pidP_D_GAIN = PIDP_D_GAIN;	pidP_I_LIMIT = PIDP_I_LIMIT; pidP_EMA_SAMPLES = PIDP_EMA_SAMPLES;
	PIDinit( &pitchPID[0], &pidP_P_GAIN, &pidP_I_GAIN, &pidP_D_GAIN, &pidP_I_LIMIT, &pidP_EMA_SAMPLES );
	PIDinit( &pitchPID[1], &pidP_P_GAIN, &pidP_I_GAIN, &pidP_D_GAIN, &pidP_I_LIMIT, &pidP_EMA_SAMPLES );
	
	/*Set default values and init speedPID controllers*/
	pidS_P_GAIN = PIDS_P_GAIN;	pidS_I_GAIN = PIDS_I_GAIN;	pidS_D_GAIN = PIDS_D_GAIN;	pidS_I_LIMIT = PIDS_I_LIMIT; pidS_EMA_SAMPLES = PIDS_EMA_SAMPLES;
	PIDinit( &speedPID[0], &pidS_P_GAIN, &pidS_I_GAIN, &pidS_D_GAIN, &pidS_I_LIMIT, &pidS_EMA_SAMPLES );
	PIDinit( &speedPID[1], &pidS_P_GAIN, &pidS_I_GAIN, &pidS_D_GAIN, &pidS_I_LIMIT, &pidS_EMA_SAMPLES );
	
	//Get estimate of starting angle and specify complementary filter and kalman filter start angles
	getOrientation();
	kalmanAngle = filteredPitch = i2cPitch;
	setkalmanangle( filteredPitch );
	filteredRoll = i2cRoll;
	
	print( "Eddie startup complete. Hold me upright to begin\r\n" );
	
	double gy_scale = 0.01;
	last_PID_ms = last_gy_ms = current_milliseconds();
	
	while(Running)
	{
		GetEncoders( EncoderPos );
		
		if( fabs(GetEncoder()) > 2000 && !inRunAwayState )
		{
			print( "Help! I'm running and not moving.\r\n");
			ResetEncoders();
			inRunAwayState=1;
		}
		
		/*Read IMU and calculate rough angle estimates*/
		getOrientation();
		
		/*Calculate time since last IMU reading and determine gyro scale (dt)*/
		gy_scale = ( current_milliseconds() - last_gy_ms ) / 1000.0f;
	
		last_gy_ms = current_milliseconds();
		
		/*Complementary filters to smooth rough pitch and roll estimates*/
		filteredPitch = 0.995 * ( filteredPitch + ( gy * gy_scale ) ) + ( 0.005 * i2cPitch );
		filteredRoll = 0.98 * ( filteredRoll + ( gx * gy_scale ) ) + ( 0.02 * i2cRoll );

		/*Kalman filter for most accurate pitch estimates*/	
		kalmanAngle = -getkalmanangle(filteredPitch, gy, gy_scale /*dt*/);

		/* Monitor angles to determine if Eddie has fallen too far... or if Eddie has been returned upright*/
		if ( ( inRunAwayState || ( fabs( kalmanAngle ) > 50 || fabs( filteredRoll ) > 45 ) ) && !inFalloverState ) 
		{
#ifndef DISABLE_MOTORS
			motor_driver_standby(1);
#endif
			inFalloverState = 1;
			print( "Help! I've fallen over and I can't get up =)\r\n");
		} 
		else if ( fabs( kalmanAngle ) < 10 && inFalloverState && fabs( filteredRoll ) < 20 )
		{
			if ( ++inSteadyState == 100 )
			{
				inRunAwayState = 0;
				inSteadyState = 0;
#ifndef DISABLE_MOTORS
				motor_driver_standby(0);
#endif
				inFalloverState = 0;
				print( "Thank you!\r\n" );
			}
		}
		else
		{
			inSteadyState = 0;
		}

		if ( !inFalloverState )
		{
			/* Drive operations */
			smoothedDriveTrim = ( 0.99 * smoothedDriveTrim ) + ( 0.01 * driveTrim );
			if( smoothedDriveTrim != 0 ) 
			{
				EncoderAddPos(smoothedDriveTrim); //Alter encoder position to generate movement
			}
			
			/* Turn operations */
			if( turnTrim != 0  )
			{
				EncoderAddPos2( turnTrim, -turnTrim ); //Alter encoder positions to turn
			}
						
			double timenow = current_milliseconds();

			speedPIDoutput[0] = PIDUpdate( 0, EncoderPos[0], timenow - last_PID_ms, &speedPID[0] );//Wheel Speed PIDs
			speedPIDoutput[1] = PIDUpdate( 0, EncoderPos[1], timenow - last_PID_ms, &speedPID[1] );//Wheel Speed PIDs
			pitchPIDoutput[0] = PIDUpdate( speedPIDoutput[0], kalmanAngle, timenow - last_PID_ms, &pitchPID[0] );//Pitch Angle PIDs		
			pitchPIDoutput[1] = PIDUpdate( speedPIDoutput[1], kalmanAngle, timenow - last_PID_ms, &pitchPID[1] );//Pitch Angle PIDs
			
			last_PID_ms = timenow;
			
			//Limit PID output to +/-100 to match 100% motor throttle
			if ( pitchPIDoutput[0] > 100.0 )  pitchPIDoutput[0] = 100.0;
			if ( pitchPIDoutput[1] > 100.0 )  pitchPIDoutput[1] = 100.0;
			if ( pitchPIDoutput[0] < -100.0 ) pitchPIDoutput[0] = -100.0;
			if ( pitchPIDoutput[1] < -100.0 ) pitchPIDoutput[1] = -100.0;

		}
		else //We are inFalloverState
		{
			ResetEncoders();
			pitchPID[0].accumulatedError = 0;
			pitchPID[1].accumulatedError = 0;
			speedPID[0].accumulatedError = 0;
			speedPID[1].accumulatedError = 0;
			driveTrim = 0;
			turnTrim = 0;
		}
	
#ifndef DISABLE_MOTORS
		set_motor_speed_right( pitchPIDoutput[0] );
		set_motor_speed_left( pitchPIDoutput[1] );
#endif

		if ( (!inFalloverState || outputto == UDP) && StreamData )
		{			
			print( "PIDout: %0.2f,%0.2f\tcompPitch: %6.2f kalPitch: %6.2f\tPe: %0.3f\tIe: %0.3f\tDe: %0.3f\tPe: %0.3f\tIe: %0.3f\tDe: %0.3f\r\n",
				speedPIDoutput[0], 
				pitchPIDoutput[0], 
				filteredPitch, 
				kalmanAngle,
				pitchPID[0].error, 
				pitchPID[0].accumulatedError, 
				pitchPID[0].differentialError, 
				speedPID[0].error, 
				speedPID[0].accumulatedError, 
				speedPID[0].differentialError 
				);
		}

	} //--while(Running)
	
	print( "Eddie is cleaning up...\r\n" );
	
	CloseEncoder();
	
	pthread_join(udplistenerThread, NULL);
	print( "UDP Thread Joined..\r\n" );

#ifndef DISABLE_MOTORS
	motor_driver_disable();
	print( "Motor Driver Disabled..\r\n" );
#endif
	
	print( "Eddie cleanup complete. Good Bye!\r\n" );
	return 0;
}