unsigned long loop()

in BalancingRobot/Software/RTOS/rtos_app/rtos_app.c [212:408]


unsigned long loop(void)
{
	unsigned long startPeriod = millis();


	// TODO: Read IMU, calculate Yaw, Pitch, Roll
	// ICM-20948 oritentation gives Roll as lean angle.

	float _Roll = 0.0;	// 
	float g_heading = 0.0; //
	if (g_heading < 0)
		g_heading += 360;

	loopCounter++;		// counter to ensure we have 200 items in the rollHistory array.


	// roll history is used to determine how stable the IMU readings are before unlocking the motors/telemetry
	rollHistory[rollHistoryPointer] = _Roll;
	rollHistoryPointer = (rollHistoryPointer + 1) % 200;

	float min = 360.0;
	float max = 0;
	int rollHistoryCount = 0;
	for (int x = 0; x < 200; x++)
	{
		if (rollHistory[x] != -1)
		{
			rollHistoryCount++;
			if (rollHistory[x] < min)
				min = rollHistory[x];
			if (rollHistory[x] > max)
				max = rollHistory[x];
		}
	}

	// determine whether the IMU is stable.
	if (!imuStable && rollHistoryCount == 200 && fabs(max - min) < 0.02)
	{
		imuStable = true;
	}

	// if the IMU is not stable, or the system is updating then return (motor control code after this point)
	if (!imuStable || updating)
	{
		return 0;
	}

	// see if we're close to pointing north...
	if (TurnRobotFlag)
	{
		// get a value from 0 to 15 (0 == north)
		int OrientPos=GetCompassDirection(g_heading);
		int TurnPos = GetCompassDirection(turnHeading);
		if (OrientPos == TurnPos)
		{
			details.id = MSG_TURN_DETAILS;
			details.startHeading = turnStartHeading;
			details.endHeading = g_heading;
			EnqueueIntercoreMessage(&details, sizeof(details));
			TurnRobotFlag = false;
		}
	}

	// set the PID input
	input = _Roll;

	float delta = fabs(_Roll - CalibratedSetpoint);

	static unsigned long calibrationCounter = 0;

	float setpointMotorAdjust = 0.0;

	calibrationCounter++;
	if (calibrationCounter == 10)
	{
		calibrationCounter = 0;
		if (!AutoCalibrateSetpoint && !ObstacleDetected && _Roll > 80)
		{
			setpointMotorAdjust = PIDController_Update(&pid, 0, output/100.0);
			SpeedSetpointAdjust = setpointMotorAdjust * -1;
		}
	}

	setpoint = CalibratedSetpoint + ToFSetpointAdjust + SpeedSetpointAdjust + RemoteFwdBackAdjust;

	Compute();

	if (!TurnRobotFlag && !ObstacleDetected && _Roll > 80 && RemoteFwdBackAdjust == 0 && RemoteRotateCommand == 0)
	{
		if (output > 0)
		{
			CalibratedSetpoint += 0.005;
		}
		if (output < 0)
		{
			CalibratedSetpoint -= 0.005;
		}
	}


#ifdef SHOW_LOG
		printf("Calibrated Setpoint %3.2f | Setpoint %3.2f (Tweak %3.2f) [AutoCalib %c | calibStarted %c | Tick %d] | Delta %3.2f | Output %3.2f\n", CalibratedSetpoint, setpoint, setpointTweak, AutoCalibrateSetpoint == true ? 'Y' : 'N', autoCalibrateStarted == true ? 'Y' : 'N', AutoCalibrationTickCounter, delta, output);
#endif

	if (output == 0 || delta > CUT_OFF_ANGLE)
	{
		Tof_Active = false;
		// turn off 'GPIO6 LED'
		mtk_os_hal_pwm_config_freq_duty_normal(OS_HAL_PWM_GROUP1, PWM_CHANNEL2, PWM_PERIOD, 0);
		ToF_Settle_Counter = 0;

		// turn off motors.
		mtk_os_hal_gpio_set_output(OS_HAL_GPIO_0, 0);
		mtk_os_hal_gpio_set_output(OS_HAL_GPIO_1, 0);
		mtk_os_hal_gpio_set_output(OS_HAL_GPIO_2, 0);
		mtk_os_hal_gpio_set_output(OS_HAL_GPIO_12, 0);
		mtk_os_hal_gpio_set_output(OS_HAL_GPIO_13, 0);

		mtk_os_hal_pwm_config_freq_duty_normal(OS_HAL_PWM_GROUP1, PWM_CHANNEL0, PWM_PERIOD, 0);
		mtk_os_hal_pwm_config_freq_duty_normal(OS_HAL_PWM_GROUP1, PWM_CHANNEL1, PWM_PERIOD, 0);
	}
	else
	{
		if (Tof_Active == false)
		{
			ToF_Settle_Counter++;
			if (ToF_Settle_Counter == TOF_STABILIZE_PERIOD)
			{
				ToF_Settle_Counter = 0;
				Tof_Active = true;
				// turn on 'GPIO6 LED'
				// mtk_os_hal_pwm_config_freq_duty_normal(OS_HAL_PWM_GROUP1, PWM_CHANNEL2, PWM_PERIOD, 1000);
			}
		}

		unsigned long duty = abs(output)*PWM_MULTIPLIER;
		unsigned long dutyLeft = duty;
		unsigned long dutyRight = duty;

		static bool Tick = false;

		// add turning value.
		if ((TurnRobotFlag || RemoteRotateCommand != 0) && Tick && !ObstacleDetected)
		{
			if (TurnRobotFlag || RemoteRotateCommand)
			{
				if (output > 0)
				{
					if (!RotateClockwise)
					{
						dutyLeft = (duty + SPIN_OFFSET) % 1000;
					}
					else
					{
						dutyRight = (duty + SPIN_OFFSET) % 1000;
					}
				}
				if (output < 0)
				{
					if (!RotateClockwise)
					{
						dutyRight = (duty + SPIN_OFFSET) % 1000;
					}
					else
					{
						dutyLeft = (duty + SPIN_OFFSET) % 1000;
					}
				}
			}
		}

		if (output > 0)
		{
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_0, 0);
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_1, 1);
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_2, 1);
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_12, 0);
		}
		else
		{
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_0, 1);
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_1, 0);
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_2, 0);
			mtk_os_hal_gpio_set_output(OS_HAL_GPIO_12, 1);
		}

		Tick = !Tick;

		mtk_os_hal_gpio_set_output(OS_HAL_GPIO_13, 1);
		mtk_os_hal_pwm_config_freq_duty_normal(OS_HAL_PWM_GROUP1, PWM_CHANNEL0, PWM_PERIOD, dutyLeft);
		mtk_os_hal_pwm_config_freq_duty_normal(OS_HAL_PWM_GROUP1, PWM_CHANNEL1, PWM_PERIOD, dutyRight);
	}

	unsigned long timePeriod = millis() - startPeriod;

	return timePeriod;
}