コード例 #1
0
ファイル: motors.c プロジェクト: jiezhi320/autoquadfc
void motorsInit(void) {
    float sumPitch, sumRoll, sumYaw;
    int i;

    AQ_NOTICE("Motors init\n");

    memset((void *)&motorsData, 0, sizeof(motorsData));

    if (p[MOT_FRAME] > 0.01f && p[MOT_FRAME] < 4.01f) {
        AQ_NOTICE("Motors: ERROR! Predefined frame types are no longer supported.\n");
        return;
    }

    motorsData.distribution = (motorsPowerStruct_t *)&p[MOT_PWRD_01_T];

    sumPitch = 0.0f;
    sumRoll = 0.0f;
    sumYaw = 0.0f;

    for (i = 0; i < MOTORS_NUM; i++) {
        motorsPowerStruct_t *d = &motorsData.distribution[i];

        if (d->throttle != 0.0f || d->pitch != 0.0f || d->roll != 0.0f || d->yaw != 0.0f) {

            // CAN LO
            if (((uint32_t)p[MOT_CANL]) & (1<<i))
                motorsCanInit(i);
            // CAN HI (PDB)
            else if (((uint32_t)p[MOT_CANH]) & (1<<i))
                motorsCanInit(i+16);
            // PWM
            else if (i < PWM_NUM_PORTS)
                motorsPwmInit(i);

            motorsData.active[i] = 1;
            motorsData.activeList[motorsData.numActive++] = i;

            sumPitch += d->pitch;
            sumRoll += d->roll;
            sumYaw += d->yaw;
        }
    }

    if (fabsf(sumPitch) > 0.01f)
        AQ_NOTICE("Motors: Warning pitch control imbalance\n");

    if (fabsf(sumRoll) > 0.01f)
        AQ_NOTICE("Motors: Warning roll control imbalance\n");

    if (fabsf(sumYaw) > 0.01f)
        AQ_NOTICE("Motors: Warning yaw control imbalance\n");

#ifdef MOTORS_CAN_LOGGING
    if (p[MOT_CANL] != 0.0f || p[MOT_CANH] != 0.0f)
        motorsSetupLogging();
#endif

    motorsSetCanGroup();
    motorsOff();
    canTelemRegister(motorsReceiveTelem, CAN_TYPE_ESC);
}
コード例 #2
0
ファイル: main.c プロジェクト: mackncheesiest/ECE372Labs
int main(void)
{
    SYSTEMConfigPerformance(SYS_CLOCK);
    
    enableInterrupts();
    initADC();
    initTimer2(); //for PWM
    initPWM();
    initLCD();
    initTimer4(); //for pwm
    initSW();
    
    int track = 1;
    int SpeedR = 0;
    int SpeedL = 0;
    int ones = 0;
    int dec = 0;
    float voltage = 0;

    //Actual main state machine loop
    while(1)
    {
        Speed = ADC1BUF0;
        
        moveCursorLCD(0,0);
        voltage = Speed * ((double)3.3/1023);
        ones = floor(voltage);
        dec = (voltage - ones) * 10;
        printCharLCD('0'+ones);
        printCharLCD('.');
        printCharLCD('0'+dec);
        printCharLCD('V');
        
       delayUs(10000); //10ms - Just to help the LCD not strobe too much
        
        switch(state)
        {
            case wait_Press: //handled by ISR
                break;
            case debouncePress:
                state = wait_Release;
                break;
            case wait_Release: //handled by ISR
                break;
            case debounceRelease:
                if (track == 1){
                    state = forward;
                }
                if (track == 2){
                    state = idle2;
                }
                if (track == 3){
                    state = reverse;
                }
                if (track == 4){
                    state = idle1;
                }
                break;
            case idle1:
                track = 1;
                motorsOff();
                state = wait_Press;
                break;
            case forward:
                track = 2;       
                if(Speed == 511){
                    SpeedR = 1023;
                    SpeedL = 1023;
                }
                else if(Speed < 511){
                    SpeedR = 1023;
                    SpeedL = (2*Speed);
                }
                else if(Speed > 511){
                    SpeedR = 2*(1023 - Speed);
                    SpeedL = 1023;
                }
                else if (Speed == 1023){
                    SpeedR = 0;
                    SpeedL = 1023;
                }
                else if (Speed == 0){
                    SpeedR = 1023;
                    SpeedL = 0;
                }                
                RightMotor_Write(SpeedR);
                LeftMotor_Write(SpeedL);
                break;
            case idle2:
                track = 3;
                motorsOff();
                state = wait_Press;
                break;
            case reverse:
                track = 4;
                if(Speed == 511){
                    SpeedR = 1023;
                    SpeedL = 1023;
                }
                else if(Speed < 511){
                    SpeedR = 1023;
                    SpeedL = 2*Speed;
                }
                else if(Speed > 511){
                    SpeedR = 2*(1023 - Speed);
                    SpeedL = 1023;
                }
                else if (Speed == 1023){
                    SpeedR = 1023;
                    SpeedL = 0;
                }
                else if (Speed == 0){
                    SpeedR = 0;
                    SpeedL = 1023;
                }

                
                RightMotor_Write(0-SpeedR); //maybe it needs the zero to be interpreted as negative?
                LeftMotor_Write(0-SpeedL);
                break;                       
        }
    }
    
    return 0;
}
コード例 #3
0
ファイル: pwm.c プロジェクト: mackncheesiest/ECE372Labs
void turnAround() {
    LeftMotor_Write(-850);
    RightMotor_Write(850);
    delayUs(1500000);
    motorsOff();    
}
コード例 #4
0
ファイル: control.c プロジェクト: tenyan/quadfork
void controlTaskCode(void *unused) {
	float yaw;
	float throttle;
	float ratesDesired[3];
	uint16_t overrides[3];
#ifdef USE_QUATOS
	float quatDesired[4];
	float ratesActual[3];
#else
	float pitch, roll;
	float pitchCommand, rollCommand, ruddCommand;
#endif	// USE_QUATOS

	AQ_NOTICE("Control task started\n");

	// disable all axes' rate overrides
	overrides[0] = 0;
	overrides[1] = 0;
	overrides[2] = 0;

	while (1) {
		// wait for work
		CoWaitForSingleFlag(imuData.dRateFlag, 0);

		// this needs to be done ASAP with the freshest of data
		if (supervisorData.state & STATE_ARMED) {
			if (RADIO_THROT > p[CTRL_MIN_THROT] || navData.mode > NAV_STATUS_MANUAL) {
				supervisorThrottleUp(1);

				// are we in altitude hold mode?
				if (navData.mode > NAV_STATUS_MANUAL) {
					// override throttle with nav's request
					throttle = pidUpdate(navData.altSpeedPID, navData.holdSpeedAlt, -VELOCITYD) * MOTORS_SCALE / RADIO_MID_THROTTLE;

					// don't allow negative throttle to be built up
					if (navData.altSpeedPID->iState < 0.0f) {
						navData.altSpeedPID->iState = 0.0f;
					}
				} else {
					throttle = ((uint32_t)RADIO_THROT - p[CTRL_MIN_THROT]) * MOTORS_SCALE / RADIO_MID_THROTTLE * p[CTRL_FACT_THRO];
				}
				// limit
				throttle = constrainInt(throttle, 1, MOTORS_SCALE);

				// if motors are not yet running, use this heading as hold heading
				if (motorsData.throttle == 0) {
					navData.holdHeading = AQ_YAW;
					controlData.yaw = navData.holdHeading;

					// Reset all PIDs
					pidZeroIntegral(controlData.pitchRatePID, 0.0f, 0.0f);
					pidZeroIntegral(controlData.rollRatePID, 0.0f, 0.0f);
					pidZeroIntegral(controlData.yawRatePID, 0.0f, 0.0f);

					pidZeroIntegral(controlData.pitchAnglePID, 0.0f, 0.0f);
					pidZeroIntegral(controlData.rollAnglePID, 0.0f, 0.0f);
					pidZeroIntegral(controlData.yawAnglePID, 0.0f, 0.0f);

					// also set this position as hold position
					if (navData.mode == NAV_STATUS_POSHOLD) {
						navUkfSetHereAsPositionTarget();
					}
				}

				// constrict nav (only) yaw rates
				yaw = compassDifference(controlData.yaw, navData.holdHeading);
				yaw = constrainFloat(yaw, -p[CTRL_NAV_YAW_RT]/400.0f, +p[CTRL_NAV_YAW_RT]/400.0f);
				controlData.yaw = compassNormalize(controlData.yaw + yaw);

				// DVH overrides direct user pitch / roll requests
				if (navData.mode != NAV_STATUS_DVH) {
					controlData.userPitchTarget = RADIO_PITCH * p[CTRL_FACT_PITC];
					controlData.userRollTarget = RADIO_ROLL * p[CTRL_FACT_ROLL];
				} else {
					controlData.userPitchTarget = 0.0f;
					controlData.userRollTarget = 0.0f;
				}

				// navigation requests
				if (navData.mode > NAV_STATUS_ALTHOLD) {
					controlData.navPitchTarget = navData.holdTiltN;
					controlData.navRollTarget = navData.holdTiltE;
				} else {
					controlData.navPitchTarget = 0.0f;
					controlData.navRollTarget = 0.0f;
				}

				// manual rate cut through for yaw
				if (RADIO_RUDD > p[CTRL_DEAD_BAND] || RADIO_RUDD < -p[CTRL_DEAD_BAND]) {
					// fisrt remove dead band
					if (RADIO_RUDD > p[CTRL_DEAD_BAND]) {
						ratesDesired[2] = (RADIO_RUDD - p[CTRL_DEAD_BAND]);
					} else {
						ratesDesired[2] = (RADIO_RUDD + p[CTRL_DEAD_BAND]);
					}

					// calculate desired rate based on full stick scale
					ratesDesired[2] = ratesDesired[2] * p[CTRL_MAN_YAW_RT] * DEG_TO_RAD * (1.0f / 700.0f);

					// keep up with actual craft heading
					controlData.yaw = AQ_YAW;
					navData.holdHeading = AQ_YAW;

					// request override
					overrides[2] = CONTROL_MIN_YAW_OVERRIDE;
				} else {
					// currently overriding?
					if (overrides[2] > 0) {
						// request zero rate
						ratesDesired[2] = 0.0f;

						// follow actual craft heading
						controlData.yaw = AQ_YAW;
						navData.holdHeading = AQ_YAW;

						// decrease override timer
						overrides[2]--;
					}
				}

#ifdef USE_QUATOS
				// determine which frame of reference to control from
				if (navData.mode <= NAV_STATUS_ALTHOLD)
					// craft frame - manual
				{
					eulerToQuatYPR(quatDesired, controlData.yaw, controlData.userPitchTarget, controlData.userRollTarget);
				} else
					// world frame - autonomous
				{
					eulerToQuatRPY(quatDesired, controlData.navRollTarget, controlData.navPitchTarget, controlData.yaw);
				}

				// reset controller on startup
				if (motorsData.throttle == 0) {
					quatDesired[0] = UKF_Q1;
					quatDesired[1] = UKF_Q2;
					quatDesired[2] = UKF_Q3;
					quatDesired[3] = UKF_Q4;
					quatosReset(quatDesired);
				}

				ratesActual[0] = IMU_DRATEX + UKF_GYO_BIAS_X;
				ratesActual[1] = IMU_DRATEY + UKF_GYO_BIAS_Y;
				ratesActual[2] = IMU_DRATEZ + UKF_GYO_BIAS_Z;
				quatos(&UKF_Q1, quatDesired, ratesActual, ratesDesired, overrides);

				quatosPowerDistribution(throttle);
				motorsSendThrust();
				motorsData.throttle = throttle;
#else

				// smooth
				controlData.userPitchTarget = utilFilter3(controlData.userPitchFilter, controlData.userPitchTarget);
				controlData.userRollTarget = utilFilter3(controlData.userRollFilter, controlData.userRollTarget);

				// smooth
				controlData.navPitchTarget = utilFilter3(controlData.navPitchFilter, controlData.navPitchTarget);
				controlData.navRollTarget = utilFilter3(controlData.navRollFilter, controlData.navRollTarget);

				// rotate nav's NE frame of reference to our craft's local frame of reference
				pitch = controlData.navPitchTarget * navUkfData.yawCos - controlData.navRollTarget * navUkfData.yawSin;
				roll  = controlData.navRollTarget * navUkfData.yawCos + controlData.navPitchTarget * navUkfData.yawSin;

				// combine nav & user requests (both are already smoothed)
				controlData.pitch = pitch + controlData.userPitchTarget;
				controlData.roll = roll + controlData.userRollTarget;

				if (p[CTRL_PID_TYPE] == 0) {
					// pitch angle
					pitchCommand = pidUpdate(controlData.pitchAnglePID, controlData.pitch, AQ_PITCH);
					// rate
					pitchCommand += pidUpdate(controlData.pitchRatePID, 0.0f, IMU_DRATEY);

					// roll angle
					rollCommand = pidUpdate(controlData.rollAnglePID, controlData.roll, AQ_ROLL);
					// rate
					rollCommand += pidUpdate(controlData.rollRatePID, 0.0f, IMU_DRATEX);
				} else if (p[CTRL_PID_TYPE] == 1) {
					// pitch rate from angle
					pitchCommand = pidUpdate(controlData.pitchRatePID, pidUpdate(controlData.pitchAnglePID, controlData.pitch, AQ_PITCH), IMU_DRATEY);

					// roll rate from angle
					rollCommand = pidUpdate(controlData.rollRatePID, pidUpdate(controlData.rollAnglePID, controlData.roll, AQ_ROLL), IMU_DRATEX);
				}


				else if (p[CTRL_PID_TYPE] == 2) {

					// pitch angle
					pitchCommand = pidUpdate(controlData.pitchAnglePID, controlData.pitch, AQ_PITCH);
					// rate
					pitchCommand += pidUpdate(controlData.pitchRatePID, 0.0f, IMU_DRATEY);

					int axis = 0; // ROLL
					float PID_P = 3.7;
					float PID_I = 0.031;
					float PID_D = 23.0;


					float           error, errorAngle, AngleRateTmp, RateError, delta, deltaSum;
					float           PTerm, ITerm, PTermACC = 0, ITermACC = 0, PTermGYRO = 0, ITermGYRO = 0, DTerm;
					static int16_t  lastGyro[3] = { 0, 0, 0 };
					static float    delta1[3], delta2[3];
					static float    errorGyroI[3] = { 0, 0, 0 }, errorAngleI[2] = { 0, 0 };
					static float    lastError[3]  = { 0, 0, 0 }, lastDTerm[3]   = { 0, 0, 0 }; // pt1 element http://www.multiwii.com/forum/viewtopic.php?f=23&t=2624;
					static int16_t  axisPID[3];
					static float rollPitchRate = 0.0;
					static float newpidimax = 0.0;
					float dT;
					uint8_t ANGLE_MODE = 0;
					uint8_t HORIZON_MODE = 0;

					uint16_t cycleTime = IMU_LASTUPD -
										 controlData.lastUpdate;                                          // this is the number in micro second to achieve a full loop, it can differ a little and is taken into account in the PID loop

					if ((ANGLE_MODE || HORIZON_MODE)) {        // MODE relying on ACC
						errorAngle = constrainFloat(2.0f * (float)controlData.roll, -500.0f, +500.0f) - AQ_ROLL;
					}

					if (!ANGLE_MODE) {                                   //control is GYRO based (ACRO and HORIZON - direct sticks control is applied to rate PID
						AngleRateTmp = (float)(rollPitchRate + 27) * (float)controlData.roll *
									   0.0625f; // AngleRateTmp = ((int32_t) (cfg.rollPitchRate + 27) * rcCommand[axis]) >> 4;
						if (HORIZON_MODE) {
							AngleRateTmp += PID_I * errorAngle *
											0.0390625f; //increased by x10 //0.00390625f AngleRateTmp += (errorAngle * (float)cfg.I8[PIDLEVEL]) >> 8;
						}
					} else {                                                // it's the ANGLE mode - control is angle based, so control loop is needed
						AngleRateTmp = PID_P * errorAngle * 0.0223214286f; // AngleRateTmp = (errorAngle * (float)cfg.P8[PIDLEVEL]) >> 4; * LevelPprescale;
					}

					RateError         = AngleRateTmp - IMU_DRATEX;
					PTerm             = PID_P * RateError * 0.0078125f;
					errorGyroI[axis] += PID_I * RateError * (float)cycleTime / 2048.0f;
					errorGyroI[axis]  = constrainFloat(errorGyroI[axis], -newpidimax, newpidimax);
					ITerm             = errorGyroI[axis] / 8192.0f;
					delta             = RateError - lastError[axis];
					lastError[axis]   = RateError;
					delta             = delta * 16383.75f / (float)cycleTime;
					deltaSum          = delta1[axis] + delta2[axis] + delta;
					delta2[axis]      = delta1[axis];
					delta1[axis]      = delta;
					DTerm             = PID_D * deltaSum * 0.00390625f;
					axisPID[axis]     = PTerm + ITerm + DTerm;


					rollCommand = AngleRateTmp;

				}

				else {
					pitchCommand = 0.0f;
					rollCommand = 0.0f;
					ruddCommand = 0.0f;
				}

				// yaw rate override?
				if (overrides[2] > 0)
					// manual yaw rate
				{
					ruddCommand = pidUpdate(controlData.yawRatePID, ratesDesired[2], IMU_DRATEZ);
				} else
					// seek a 0 deg difference between hold heading and actual yaw
				{
					ruddCommand = pidUpdate(controlData.yawRatePID, pidUpdate(controlData.yawAnglePID, 0.0f, compassDifference(controlData.yaw, AQ_YAW)),
											IMU_DRATEZ);
				}

				rollCommand = constrainFloat(rollCommand, -p[CTRL_MAX], p[CTRL_MAX]);
				pitchCommand = constrainFloat(pitchCommand, -p[CTRL_MAX], p[CTRL_MAX]);
				ruddCommand = constrainFloat(ruddCommand, -p[CTRL_MAX], p[CTRL_MAX]);

				motorsCommands(throttle, pitchCommand, rollCommand, ruddCommand);
#endif

			}
			// no throttle input
			else {
				supervisorThrottleUp(0);

				motorsOff();
			}
		}
		// not armed
		else {
			motorsOff();
		}

		controlData.lastUpdate = IMU_LASTUPD;
		controlData.loops++;
	}
}
コード例 #5
0
ファイル: systemtimer.c プロジェクト: rushipatel/ANTZ
/*****************************************************
 *  Timer 5 is used to provide the main system clock
 *  It generates an interrupt every millisecond
 *
 *  This ISR is where most of the actual work gets done.
 *  with the sensors running and the straights profiler
 *  active, this interrupt takes about 220us of which
 *  120us is processing the sensors
 *****************************************************/
void _ISR SYSTIM_INTERRUPT(void)
{
	int pidOut;
	unsigned char rxBytes;
	/* reset the interrupt flag */
	SYSTIM_IF = 0;
	//LED_ON;
	tickCount++;      
	millisecondCount--;
	commCount++;
	
	if(!GDO0)
	{
		rxBytes = CC2500_receive_packet();
		if(rxBytes>PACKET_LEN)
		{
			CC2500_idle_mode();
			CC2500_clear_rx_fifo();
			CC2500_clear_tx_fifo();
			CC2500_receive_mode();
			commEnabled = FALSE;
		}
		else
			commEnabled = TRUE;
		if(newPacket)
		{
			deassamble_packet();
			getFellowCoveredSqrs();
			my.obzClear = OBZ_clear();
			if(inOBZ(fellow.location))
			{
				LED_ON;
			}
			else
			{
				LED_OFF;
			}
			dataUpdated = TRUE;
			newPacket = FALSE;
			noCommCount = 0;
		}
		else
			noCommCount++;
	}
	if((commCount>=6)&&commEnabled)
	{
		assamble_packet();
		if(!GDO0)
		{
			CC2500_transmit_packet();
			commCount = 0;
		}
	}
	else if(commCount==4)
	{
		CC2500_idle_mode();
		__delay_us(1);
		CC2500_clear_rx_fifo();
		__delay_us(1);
		CC2500_clear_tx_fifo();
		__delay_us(1);
		CC2500_receive_mode();
	}
	if(!(tickCount&1))
		readCubeSensors();
	
	if(tickCount>300000L)
	{
		motorsOff();
		sensorsOff();
		stopSystemTimer();
		LED_ON;
	}
	doButtons();  
	readLineSensors();
	readCounters();
	doProfiler();
	
	pidOut = doPID( &left_PID_param);
	if( pidOut < -MOTORS_MAX_DC )
		pidOut = -MOTORS_MAX_DC;
	else if( pidOut > MOTORS_MAX_DC )
		pidOut = MOTORS_MAX_DC;
	motorsLeftSetDutyCycle(pidOut);
	
	pidOut = doPID( &right_PID_param);
	if( pidOut < -MOTORS_MAX_DC )
		pidOut = -MOTORS_MAX_DC;
	else if( pidOut > MOTORS_MAX_DC )
		pidOut = MOTORS_MAX_DC;
	motorsRightSetDutyCycle(pidOut);
	
	//LED_OFF;
	
}
コード例 #6
0
ファイル: main.c プロジェクト: mackncheesiest/ECE372Labs
int main(void) {
    
    SYSTEMConfigPerformance(40000000); //System clock is 40MHz
    //Because interrupts are good to have
    enableInterrupts();
    //Because ADC is good to have
    initADC();
    //Because a timer is good to have for PWM
    initTimer2();
    //Because PWM is good to have
    initPWM();
//    initMotorDirPins();
    //Because the delayUs function is typically pretty good to have
    initTimer4();
    //Because UART is good to have for interfacing with our speech chip
    initUART(40000000);
    //Because a talking robot is the absolute best thing to have
    //initSpeakJet();
    
    initSevenSegment();            
    
    initSW();
    
    int HelloBytes[] = {0, 0, 0, 0b01110110, 0b01111001, 0b00111000, 0b00111000, 0b00111111, 0, 0, 0};
    int helloCounter = 2;
    
    int myCounter = 0;    
    int timesInFwd = 0;
    //sendSpeakjet(initByteArray);
    
    while(1) {
                
        if(millis >= 5000) //if it's been some seconds
        {
            millis = 0; //reset the timer    
            //tell speakjet to speak state here                
            sendSpeakjet(AllYour);
        }
            
        if(ScrollMillis >= 600)
        {
            ScrollMillis = 0;
            helloCounter = ((helloCounter + 1) % 8);
            sevenSeg_write(0, HelloBytes[WRAPPOS((helloCounter-3), 8)]);
            sevenSeg_write(1, HelloBytes[WRAPPOS(helloCounter-2,8)]);
            sevenSeg_write(2, HelloBytes[(helloCounter-1) % 8]);
            sevenSeg_write(2, HelloBytes[WRAPPOS((helloCounter-1), 8)]);
            sevenSeg_write(3, HelloBytes[(helloCounter)]);
        }
            
        switch(myState) {
            case idle:
                motorsOff();
                break;
            case init:
                //Wait for a button press to start us up
                motorsOff();
                sendSpeakjet(BiteMy);
                delayUs(3000000);                
                myState = backwards;
                break;
            case backwards:
                timesInFwd = 0;
                LeftMotor_Write(-800);
                RightMotor_Write(-800);
                if(leftPairReading < THRESHOLD && rightPairReading < THRESHOLD)
                    myState = pivot_right;
                else if (rightPairReading < THRESHOLD)
                    myState = turnL_back;
                else if (leftPairReading < THRESHOLD)
                    myState = turnR_back;
                else
                    myState = backwards;
                break;
            case turnR_back:
                turnRight_back(73); //makes the LEFT motor turn at near full power. Yes, it IS the left motor and not the right one.
                turnLeft_back(300);
                sampleIRPairs(&leftPairReading, &rightPairReading, 10);
//                myState = (rightPairReading >= THRESHOLD) ? forward : turnR;
                if (leftPairReading < THRESHOLD && rightPairReading < THRESHOLD) //both dark
                    myState = pivot_right;
                else if (rightPairReading < THRESHOLD) 
                    myState = turnR_back;
                else if (leftPairReading < THRESHOLD) 
                    myState = turnL_back;
                else 
                    myState = backwards;
                break;
            case turnL_back:
                turnRight_back(300); //makes the LEFT motor turn at near full power. Yes, it IS the left motor and not the right one.
                turnLeft_back(73);
                sampleIRPairs(&leftPairReading, &rightPairReading, 10);
//                myState = (rightPairReading >= THRESHOLD) ? forward : turnR;
                if (leftPairReading < THRESHOLD && rightPairReading < THRESHOLD) //both dark
                    myState = pivot_right;
                else if (rightPairReading < THRESHOLD) 
                    myState = turnR_back;
                else if (leftPairReading < THRESHOLD) 
                    myState = turnL_back;
                else 
                    myState = backwards;
                break;
            case pivot_right:
//                if(leftPairReading >= THRESHOLD) //left is light
//                    myState = forward;
//                break;
                RightMotor_Write(-650);
                LeftMotor_Write(700);
                if(rightPairReading > THRESHOLD)
                    myState = forward;
                break;
            case turnR:
//                turnRight(512);
                turnRight(73); //makes the LEFT motor turn at near full power. Yes, it IS the left motor and not the right one.
                turnLeft(800);
                sampleIRPairs(&leftPairReading, &rightPairReading, 10);
//                myState = (rightPairReading >= THRESHOLD) ? forward : turnR;
                if (leftPairReading < THRESHOLD && rightPairReading < THRESHOLD) //both dark
                    myState = turnR;
                else if (rightPairReading < THRESHOLD) 
                    myState = turnR;
                else if (leftPairReading < THRESHOLD) 
                    myState = turnL;
                else 
                    myState = forward;
                break;
            case turnL:
//                turnLeft(512);
                turnLeft(73); //makes RIGHT motor run at near full power. Yes, it IS the right motor, not the left one.
                turnRight(800);
                sampleIRPairs(&leftPairReading, &rightPairReading, 10);
//                myState = (leftPairReading >= THRESHOLD) ? forward : turnL;
                if (leftPairReading < THRESHOLD && rightPairReading < THRESHOLD) 
                    myState = turnR;
                else if (rightPairReading < THRESHOLD) 
                    myState = turnR;
                else if (leftPairReading < THRESHOLD)  
                    myState = turnL;
                else 
                    myState = forward;                
                break;
            case forward:
                if(timesInFwd >= 25000)
                {
                    sendSpeakjet(finishedPhrase);
                    myState = backwards;
//                    myState = idle;
                    break;
                }
                timesInFwd++;
                goForward();
                sampleIRPairs(&leftPairReading, &rightPairReading, 100);
                if (rightPairReading < THRESHOLD) {
                    myState = turnR; 
                    timesInFwd = 0;
                }
                else if (leftPairReading < THRESHOLD) { 
                    myState = turnL;
                    timesInFwd = 0;
                }
                break;
        }
    }
    
    return (EXIT_SUCCESS);
}