Ejemplo n.º 1
0
/**
* \brief ADC interrupt handler.
*/
void ADC_Handler(void)
{
	uint32_t tmp;
	uint32_t status ;

	status = adc_get_status(ADC);
	
	/* Checa se a interrupção é devido ao canal 5 */
	static float rad_antes = 0;
	if ((status & ADC_ISR_EOC5)) {
		tmp = adc_get_channel_value(ADC, ADC_POT_CHANNEL);

			ili93xx_set_foreground_color(COLOR_WHITE);
			ili93xx_draw_filled_rectangle(9, 39, ILI93XX_LCD_WIDTH,55);
			v=3.3*((float)tmp)/4095.0;
			rad=2*pi*((float)tmp)/4095.0;
			ili93xx_draw_line(120,160,120+54*arm_cos_f32(rad_antes),160+54*arm_sin_f32(rad_antes));
			ili93xx_set_foreground_color(COLOR_BLACK);
			sprintf(vet, "Tensao: %f", v);
			ili93xx_draw_string(10, 40, vet);
			ili93xx_draw_line(120,160,120+54*arm_cos_f32(rad),160+54*arm_sin_f32(rad));
			rad_antes = rad;

	}
	

	
}
Ejemplo n.º 2
0
void IMU::computeYaw(void) {
	float32_t sqrt_result, arg1, arg2;
	float32_t mag[3];
	mag[0] = magnetometer.axis_f[0];
	mag[1] = magnetometer.axis_f[1];
	mag[2] = magnetometer.axis_f[2];

	//Normalise measurement:
	arg1 = (float32_t) (mag[0]) * (mag[0]) + (mag[1]) * (mag[1]) + (mag[2]) * (mag[2]);
	arm_sqrt_f32(arg1, &sqrt_result);
	mag[0] /= sqrt_result;
	mag[1] /= sqrt_result;
	mag[2] /= sqrt_result;

	arg1 = arm_sin_f32(XRollAngleInRad) * mag[2] - arm_cos_f32(XRollAngleInRad) * mag[1];
	arg2 = arm_cos_f32(YPitchAngleInRad) * mag[0]
			+ arm_sin_f32(XRollAngleInRad) * arm_sin_f32(YPitchAngleInRad) * mag[1]
			+ arm_cos_f32(XRollAngleInRad) * arm_sin_f32(YPitchAngleInRad) * mag[2];
	ZYawAngleInRad = atan2f(arg1, arg2);

	//Correct declination, and change to compass angles
//	ZYawAngleInRad += (5.0 + (16.0 / 60.0))*PI/180.0; //Positive declination.
//	if (ZYawAngleInRad < 0) {
//		ZYawAngleInRad += 2 * PI;
//	} else if (ZYawAngleInRad > 2 * PI) {
//		ZYawAngleInRad -= 2 * PI;
//	}
}
	void process_tilt_correction(APP_Attitude_I& attitude){
		float pitch_rad = attitude.pitch*(2.0*M_PI/360.0);
		float roll_rad  = attitude.roll*(2.0*M_PI/360.0);

		float tilt_correction = throttle / (arm_cos_f32(pitch_rad*0.8) * arm_cos_f32(roll_rad*0.8));
		tilt_correction = contrain((tilt_correction - throttle), 0, 50);

		throttle += tilt_correction;
	}
Ejemplo n.º 4
0
static mp_obj_t py_image_draw_keypoints(mp_obj_t image_obj, mp_obj_t kpts_obj)
{
    image_t *image = NULL;
    py_kp_obj_t *kpts=NULL;

    /* get pointer */
    image = py_image_cobj(image_obj);
    kpts = (py_kp_obj_t*)kpts_obj;

    /* sanity checks */
    PY_ASSERT_TRUE_MSG(image->bpp == 1,
            "This function is only supported on GRAYSCALE images");
    PY_ASSERT_TYPE(kpts_obj, &py_kp_type);

    color_t cl = {.r=0xFF, .g=0xFF, .b=0xFF};
    for (int i=0; i<kpts->size; i++) {
        kp_t *kp = &kpts->kpts[i];
        float co = arm_cos_f32(kp->angle);
        float si = arm_sin_f32(kp->angle);
        imlib_draw_line(image, kp->x, kp->y, kp->x+(co*10), kp->y+(si*10));
        imlib_draw_circle(image, kp->x, kp->y, 4, &cl);
    }

    return mp_const_none;
}

static mp_obj_t py_image_find_blobs(mp_obj_t image_obj)
{
    /* C stuff */
    array_t *blobs;
    struct image *image;
    mp_obj_t blob_obj[6];

    /* MP List */
    mp_obj_t objects_list = mp_const_none;

     /* get image pointer */
    image = py_image_cobj(image_obj);

    /* run color dector */
    blobs = imlib_count_blobs(image);

    /* Create empty Python list */
    objects_list = mp_obj_new_list(0, NULL);

    if (array_length(blobs)) {
        for (int j=0; j<array_length(blobs); j++) {
             blob_t *r = array_at(blobs, j);
             blob_obj[0] = mp_obj_new_int(r->x);
             blob_obj[1] = mp_obj_new_int(r->y);
             blob_obj[2] = mp_obj_new_int(r->w);
             blob_obj[3] = mp_obj_new_int(r->h);
             blob_obj[4] = mp_obj_new_int(r->c);
             blob_obj[5] = mp_obj_new_int(r->id);
             mp_obj_list_append(objects_list, mp_obj_new_tuple(6, blob_obj));
        }
    }
    array_free(blobs);
    return objects_list;
}
Ejemplo n.º 5
0
void IMU::removeCentrifugalForceEffect(void) {
	float32_t arg1 = .0, sumOfSquares = .0;
	float32_t result = .0;
	volatile float32_t centrifugalAcceleration[3] = { .0 };
	float32_t rotationThresholdInRadPerSec = 5.0;
	//Physical dimensions on board in mm
	const float32_t dx = 0.015,	//15 mm
			dy = 0.01,		//20 mm
			dz = 0.003;	//3 mm
	float32_t *const pGyroAxis = gyro.axisInRadPerS, *const pAccAxis = accelerometer.axisInMPerSsquared;

	if (pGyroAxis[0] > rotationThresholdInRadPerSec) {
		centrifugalAcceleration[1] = pGyroAxis[0] * pGyroAxis[0] * dx;
	}
	if (pGyroAxis[1] > rotationThresholdInRadPerSec) {
		centrifugalAcceleration[0] = pGyroAxis[1] * pGyroAxis[1] * dy;
	}
	if (pGyroAxis[2] > rotationThresholdInRadPerSec) {
		arm_sqrt_f32(sumOfSquares, &result);
		centrifugalAcceleration[0] = pGyroAxis[2] * pGyroAxis[2] * result;
		centrifugalAcceleration[1] = pGyroAxis[2] * pGyroAxis[2] * result;

		sumOfSquares = dx * dx + dy * dy;
		arg1 = dy / sumOfSquares;
		centrifugalAcceleration[0] *= arm_sin_f32(arg1);
		arg1 = dx / sumOfSquares;
		centrifugalAcceleration[1] *= arm_cos_f32(arg1);
	}
	pAccAxis[0] -= centrifugalAcceleration[0];
	pAccAxis[1] -= centrifugalAcceleration[1];
	pAccAxis[2] -= centrifugalAcceleration[2];
}
Ejemplo n.º 6
0
int32_t main(void) 
{ 
	float32_t diff; 
	uint32_t i; 
 
	for(i=0; i< blockSize; i++) 
    { 
        cosOutput = arm_cos_f32(testInput_f32[i]); 
		sinOutput = arm_sin_f32(testInput_f32[i]); 
 
		arm_mult_f32(&cosOutput, &cosOutput, &cosSquareOutput, 1); 
		arm_mult_f32(&sinOutput, &sinOutput, &sinSquareOutput, 1); 
 
		arm_add_f32(&cosSquareOutput, &sinSquareOutput, &testOutput, 1);
 
		/* absolute value of difference between ref and test */ 
	    diff = fabsf(testRefOutput_f32 - testOutput); 
	 
	    /* Comparison of sin_cos value with reference */ 
	    if(diff > DELTA) 
	    { 
		   status = ARM_MATH_TEST_FAILURE; 
	    } 
		 
	    if( status == ARM_MATH_TEST_FAILURE) 
	    { 
	       while(1); 
	    } 
 
    } 

    while(1);                             /* main function does not return */
} 
/*=====================================================================================================*/
void Quaternion_ToNumQ( Quaternion *pNumQ, EulerAngle *pAngE )
{
  float halfP = pAngE->Pitch/2.0f;
  float halfR = pAngE->Roll/2.0f;
  float halfY = pAngE->Yaw/2.0f;

  float sinP = arm_sin_f32(halfP);
  float cosP = arm_cos_f32(halfP);
  float sinR = arm_sin_f32(halfR);
  float cosR = arm_cos_f32(halfR);
  float sinY = arm_sin_f32(halfY);
  float cosY = arm_cos_f32(halfY);

  pNumQ->q0 = cosY*cosR*cosP + sinY*sinR*sinP;
  pNumQ->q1 = cosY*cosR*sinP - sinY*sinR*cosP;
  pNumQ->q2 = cosY*sinR*cosP + sinY*cosR*sinP;
  pNumQ->q3 = sinY*cosR*cosP - cosY*sinR*sinP;
}
Ejemplo n.º 8
0
float32_t benchAngle(drv_accelData_t *data) {
	int forCounter;
	float32_t temp;
	int angle;
	for (forCounter = 0; forCounter < 91; forCounter++) {
		temp = arm_cos_f32(forCounter);
		if (temp >= (data.x - 0.2) && temp <= (data.x + 0.2)) {
			angle = forCounter;
		}
	}
}
Ejemplo n.º 9
0
// simply take average on a square patch, not even gaussian approx
static uint8_t mean_intensity(image_t *image, i_image_t *i_image, int kp_x, int kp_y, uint32_t rot, uint32_t point)
{
    int pidx = (point/6)%8;
    float alpha, beta, theta = 0;

    if (rot) {
        theta = rot*PI_2/(float)kNB_ORIENTATION; // orientation of the pattern
    }
    beta = PI/n[pidx]*(pidx%2); // orientation offset so that groups of points on each circles are staggered
    alpha = (float)(point%n[pidx])*PI_2/(float)n[pidx]+beta+theta;

    float px = radius[pidx] * PATTERN_SCALE * arm_cos_f32(alpha);
    float py = radius[pidx] * PATTERN_SCALE * arm_sin_f32(alpha);
    float psigma = sigma[pidx] * PATTERN_SCALE;

    // get point position in image
    float xf = px+kp_x;
    float yf = py+kp_y;
    int x = (int) xf;
    int y = (int) yf;
    int imagecols = image->w;

    // calculate output:
    int ret_val;
    if (psigma < 0.5f) {
        // interpolation multipliers:
        int r_x = (xf-x)*1024;
        int r_y = (yf-y)*1024;
        int r_x_1 = (1024-r_x);
        int r_y_1 = (1024-r_y);
        uint8_t* ptr = image->data+(y*imagecols+x);
        // linear interpolation:
        ret_val = (r_x_1*r_y_1*(int)(*ptr++));
        ret_val += (r_x*r_y_1*(int)(*ptr));
        ptr += imagecols;
        ret_val += (r_x*r_y*(int)(*ptr--));
        ret_val += (r_x_1*r_y*(int)(*ptr));
        return (ret_val+512)/1024;
    } else {
        int x_left    = (int) (xf-psigma+0.5f);
        int y_top     = (int) (yf-psigma+0.5f);
        int x_right   = (int) (xf+psigma+1.5f);//integral image is 1px wider
        int y_bottom  = (int) (yf+psigma+1.5f);//integral image is 1px higher

        ret_val  = i_image->data[i_image->w*y_bottom+x_right];//bottom right corner
        ret_val -= i_image->data[i_image->w*y_bottom+x_left];
        ret_val += i_image->data[i_image->w*y_top+x_left];
        ret_val -= i_image->data[i_image->w*y_top+x_right];
        ret_val  = ret_val/( (x_right-x_left)* (y_bottom-y_top) );
        return ret_val;
    }
}
void Rotate3dVector(float vector[3], float roll, float pitch, float yaw, float Retorno[3])
{
	roll = roll/57.3;
	pitch = pitch/57.3;
	yaw = yaw/57.3;

	float A = roll;
	float B = pitch;
	float C = yaw;

	float cosA, sinA;
	float cosB, sinB;
	float cosC, sinC;

	cosA = arm_cos_f32(A);
	sinA = arm_sin_f32(A);

	cosB = arm_cos_f32(B);
	sinB = arm_sin_f32(B);

	cosC = arm_cos_f32(C);
	sinC = arm_sin_f32(C);

	float RotationMatrix_f32[9] = 	{cosB*cosC, cosC*sinA*sinB-cosA*sinC, cosA*cosC*sinB+sinA*sinC,
									cosB*sinC, cosA*cosC+sinA*sinB*sinC, -cosC*sinA+cosA*sinB*sinC,
									-sinB, cosB*cosA, cosA*cosB};
	
	arm_matrix_instance_f32 RotationMatrix;
	arm_mat_init_f32(&RotationMatrix, 3, 3, RotationMatrix_f32);

	arm_matrix_instance_f32 InVector;
	arm_mat_init_f32(&InVector, 3, 1, vector);

	arm_matrix_instance_f32 OutVector;
	arm_mat_init_f32(&OutVector, 3, 1, Retorno);

	arm_mat_mult_f32(&RotationMatrix, &InVector, &OutVector);

}
Ejemplo n.º 11
0
float getValueForCoord(float x, float y, float time) {
	//	float value = arm_sin_f32(x * 10 + time);

	float value =0.0;
	value += arm_sin_f32(x * 10 + time);
	value += arm_sin_f32(10*(x*arm_sin_f32(time/2) + y*arm_cos_f32(time/3))+time);

	float cx = x+0.5*arm_sin_f32(time/5);
	float cy = y+0.5*arm_sin_f32(time/3);

	value += arm_sin_f32( sqrtf(100 * ((cx*cx)+(cy*cy))+1)+time);

	return value;
}
Ejemplo n.º 12
0
int main()
{    
  int n;
	gpio_set_mode(P2_10, Output);
	
  for(n=0 ; n<N ; n++)
  {
    samples[2*n] = arm_cos_f32(2*PI*TESTFREQ*n/SAMPLING_FREQ);
    samples[2*n+1] = 0.0;
  }
	gpio_set(P2_10, HIGH);
  arm_cfft_f32(&arm_cfft_sR_f32_len128, samples, 0, 1);
	gpio_set(P2_10, LOW);
  while(1){}
}	
Ejemplo n.º 13
0
void FiltIntInit(FiltInt * flt )
{
	int index =0;
	double cosres;
	//Расчет коэффициентов косинусной части алгортма Фурье для первой гармоники
	for (index = 0; index < DEV_PeriodSamples; index++)
	{
#ifndef MSVC
		cosres =  arm_cos_f32(2.0f * MATH_Pi / (float)DEV_PeriodSamples*(float)index)*((int64_t)1<<32);
#else
		cosres = cos(2.0f * MATH_Pi / (float)DEV_PeriodSamples*(float)index)*((int64_t)1<<32);		
#endif
		flt->filtCoef[index] = (int64_t)cosres;
	}
}
Ejemplo n.º 14
0
void IMU::computePitchRollTilt(void) {
	float32_t arg1;
	float32_t sqrt_result;
	float32_t acc[3];
	acc[0] = accelerometer.axisInMPerSsquared[0];
	acc[1] = accelerometer.axisInMPerSsquared[1];
	acc[2] = accelerometer.axisInMPerSsquared[2];

	//Normalise measurement:
	arg1 = (float32_t) (acc[0]) * (acc[0]) + (acc[1]) * (acc[1]) + (acc[2]) * (acc[2]);
	arm_sqrt_f32(arg1, &sqrt_result);
	acc[0] /= sqrt_result;
	acc[1] /= sqrt_result;
	acc[2] /= sqrt_result;
	int8_t signZ;
	const float32_t mi = 0.01;

	//Compute angles:
	//wzor jest nieprawdziwy, gdy z=0 i y=0. nie ma jednego dobreg rozwiazania. Mozna np. aproksymowac w ten sposob:
	if (acc[2] > 0) {
		signZ = 1;
	} else {
		signZ = -1;
	}
	arg1 = (acc[2]) * (acc[2]) + mi * (acc[0]) * (acc[0]);
	arm_sqrt_f32(arg1, &sqrt_result);
	XRollAngleInRad = atan2(acc[1], signZ * sqrt_result);

	arg1 = 0;
	arg1 += (float32_t) (acc[2]) * (float32_t) (acc[2]);
	arg1 += (float32_t) (acc[1]) * (float32_t) (acc[1]);
	arm_sqrt_f32(arg1, &sqrt_result);
	YPitchAngleInRad = atan2(-(acc[0]), sqrt_result);
	//YPitchAngleInRad_2 = arm_sin_f32((float32_t)(-acc[0])/(float32_t)(g));

	arg1 = 0;
	arg1 += (float32_t) (acc[0]) * (float32_t) (acc[0]);
	arg1 += (float32_t) (acc[1]) * (float32_t) (acc[1]);
	arg1 += (float32_t) (acc[2]) * (float32_t) (acc[2]);
	arm_sqrt_f32(arg1, &sqrt_result);
	TiltAngleInRad = arm_cos_f32((acc[2]) / sqrt_result);
}
Ejemplo n.º 15
0
void body_aimming_angle()
{
	global_aimming_angle(&(global_yaw),&(global_pitch));
	
	
	/*transform global vetor form global to body*/
	
	vector_x_fc = vector_y;
	vector_y_fc = -vector_x;
	vector_z_fc = vector_z;

	//printf("%f,%f,%f\r\n",vector_x_fc,vector_y_fc,vector_z_fc);

	/*turn body by yaw,pitch,roll*/
	vector_body_x = Mq11*vector_x_fc + Mq12*vector_y_fc + Mq13*vector_z_fc;
	vector_body_y = Mq21*vector_x_fc + Mq22*vector_y_fc + Mq23*vector_z_fc;
	vector_body_z = Mq31*vector_x_fc + Mq32*vector_y_fc + Mq33*vector_z_fc;

	//printf("%f,%f,%f\r\n",vector_body_x,vector_body_y,vector_body_z);

	//printf("global_yaw,%f,global_pitch,%f\r\n",global_yaw,global_pitch);

	body_yaw   = (atan2f(vector_body_y,vector_body_x));
	body_pitch = toDeg(atan2f(-vector_body_z,(arm_cos_f32(body_yaw) * vector_body_x + arm_sin_f32(body_yaw) * vector_body_y)));
	body_yaw   = toDeg(body_yaw);

	if(body_pitch > 90.0)
	{
		body_yaw  = body_yaw + 180.0;
		body_pitch= 180.0 - body_pitch;
	}
/*	else if(body_pitch < 0.0)
	{
		body_yaw  = body_yaw + 180.0;
		body_pitch= -body_pitch;
	}
*/
	//printf("body_yaw,%f,body_pitch,%f\r\n",body_yaw,body_pitch);

}
Ejemplo n.º 16
0
/* The main process of FFT.
 * Using the butterfly algorithm.
 */
void butterfly()
{
	int le, lei, ip, m, f = DATA_LENGTH;
	int level, i, j;
	struct cmplx u, w, t;

	// Calculate the level of butterfly algorithm
	for ( level = 1; (f>>=1) != 1; ++level )
		;

	for ( m = 1; m <= level; ++m )
	{
		le = 2 << ( m - 1 );
		lei = le >> 1;

		u.real = 1.0;
		u.imag = 0.0;

		w.real = arm_cos_f32( PI / lei );
		w.imag = -arm_sin_f32( PI / lei );

		for ( j = 0; j <= lei - 1; ++j )
		{
			for ( i = j; i < DATA_LENGTH; i = i + le )
			{
				ip = i + lei;
				t = EE( fft_input[ip], u );
				fft_input[ip].real = fft_input[i].real - t.real;
				fft_input[ip].imag = fft_input[i].imag - t.imag;
				fft_input[i].real = fft_input[i].real + t.real;
				fft_input[i].imag = fft_input[i].imag + t.imag;
			}
			u = EE( u, w );
		}
	}

}	// end of bufferfly()
int32_t main(void) 
{ 
   float32_t diff; 
   uint32_t i; 

   printf("Starting Test...\n");
   for (i=0; i < blockSize; i++) 
   { 
      cosOutput = arm_cos_f32(testInput_f32[i]); 
      printf("Cos %f = %f\n", testInput_f32[i], cosOutput);
 
      sinOutput = arm_sin_f32(testInput_f32[i]); 
      printf("Sin %f = %f\n", testInput_f32[i], sinOutput);

      arm_mult_f32(&cosOutput, &cosOutput, &cosSquareOutput, 1); 
      printf("Cos squared %f = %f\n", cosOutput, cosSquareOutput);

      arm_mult_f32(&sinOutput, &sinOutput, &sinSquareOutput, 1); 
      printf("Sin squared %f = %f\n", sinOutput, sinSquareOutput);

      arm_add_f32(&cosSquareOutput, &sinSquareOutput, &testOutput, 1);
      printf("Add %f and %f = %f\n", cosSquareOutput, sinSquareOutput, testOutput);
 
      /* absolute value of difference between ref and test */ 
      diff = fabsf(testRefOutput_f32 - testOutput); 
      /* Comparison of sin_cos value with reference */ 
      if (diff > DELTA) 
      { 
         printf("Diff failure %f\n", diff);
         exit(EXIT_FAILURE); /* just for QEMU testing */
         while(1); 
      } 
   } 
   printf("Ending Test...\n");
   exit(EXIT_SUCCESS); /* just for QEMU testing */
   while(1); /* main function does not return */
} 
Ejemplo n.º 18
0
static void GPS_ISR()
{
	TIM_ClearITPendingBit(GPS_TIMER, TIM_IT_Update);
	double l1 = (double)GetEncoder1Count() * Encoder1_Fact * Encoder1_DIR;
	ClearEncoder1Count();
	double l2 = (double)GetEncoder2Count() * Encoder2_Fact * Encoder2_DIR;
	ClearEncoder2Count();
#ifndef TWO_ENCODERS
	double l3 = (double)GetEncoder3Count() * Encoder3_Fact * Encoder3_DIR;
	ClearEncoder3Count();
#endif
	static double lastV = 0;

#ifdef TWO_ENCODERS
	if ( ABS(l1) < ROTATE_MESURE && ABS(l2) < ROTATE_MESURE)
	{
		g_isRotate = FALSE;
	}
	else
	{
		g_isRotate = TRUE;
	}
#else
	if ( ABS(l1 - l3) < ROTATE_MESURE )
	{
		g_isRotate = FALSE;
	}
	else
	{
		g_isRotate = TRUE;
	}
#endif

	static double LastDeg = 0;
	double currentDeg = CalculateGyroDeg();
	double deltaDeg = currentDeg - LastDeg ;
	double degData = (LastDeg + currentDeg);
	if (deltaDeg > 180 )
	{
		deltaDeg -= 360;
		degData += 360;
	}
	else if (deltaDeg < -180)
	{
		deltaDeg += 360;
		degData += 360;
	}
	g_AnglurSpeed = deltaDeg * 200;
	l1 -= deltaDeg * Encoder1_RotateFact;
	l2 -= deltaDeg * Encoder2_RotateFact;
	float _ts = l1 * l1 + l2 * l2;
	arm_sqrt_f32(_ts,&_ts);
	g_linerSpeed =  _ts * 200;
	lastV = g_linerSpeed;
#ifndef TWO_ENCODERS
	l3 -= deltaDeg * Encoder3_RotateFact;

	l1 = (l1 + l3) / 2.0;
#endif
	//计算等效的平移方向
	//
	degData = degData *0.5f + ANGLE_C;
	degData *= DEG2RAD;
	LastDeg = currentDeg;

	float degCosData, degSinData;
	degCosData = arm_cos_f32(degData);
	degSinData = arm_sin_f32(degData);
	double deltaX = l2 * degCosData -  l1 * degSinData ;
	double deltaY = l1 * degCosData +  l2 * degSinData ;

	g_NowlinerSpeedAngle = atan2(deltaY , deltaX) * RAD2DEG;
	g_X += deltaX;
	g_Y += deltaY;

}
Ejemplo n.º 19
0
CCM_FUNC static THD_FUNCTION(ThreadKnock, arg)
{
  (void)arg;
  chRegSetThreadName("Knock");

  q15_t* knockDataPtr;
  size_t knockDataSize;

  float32_t maxValue = 0;
  uint32_t maxIndex = 0;
  uint16_t i;

  /* ADC 3 Ch1 Offset. -2048 */
  ADC3->OFR1 = ADC_OFR1_OFFSET1_EN | ((1 << 26) & ADC_OFR1_OFFSET1_CH) | (2048 & 0xFFF);
  dacPutChannelX(&DACD1, 0, 2048); // This sets the offset for the knock ADC opamp.

  chThdSleepMilliseconds(200);
  adcStartConversion(&ADCD3, &adcgrpcfg_knock, samples_knock, ADC_GRP2_BUF_DEPTH);

  /* Initialize the CFFT/CIFFT module */
  arm_rfft_fast_instance_f32 S1;
  arm_rfft_fast_init_f32(&S1, FFT_SIZE);

  while (TRUE)
  {
    while (!recvFreeSamples(&knockMb, (void*)&knockDataPtr, &knockDataSize))
      chThdSleepMilliseconds(2);

    /* Copy and convert ADC samples */
    for (i=0; i<FFT_SIZE*2; i+=4)
    {
      /* Hann Window */
      float32_t multiplier = (1.0 - arm_cos_f32((2.0*PI*(float32_t)i)/(((float32_t)FFT_SIZE*2.0)-1.0)));
      input[i] = multiplier*(float32_t)knockDataPtr[i];
      input[i+1] = multiplier*(float32_t)knockDataPtr[i+1];
      input[i+2] = multiplier*(float32_t)knockDataPtr[i+2];
      input[i+3] = multiplier*(float32_t)knockDataPtr[i+3];
    }

    /* Process the data through the RFFT module */
    arm_rfft_fast_f32(&S1, input, output, 0);

    /* Process the data through the Complex Magnitude Module for
    calculating the magnitude at each bin */
    arm_cmplx_mag_f32(output, mag_knock, FFT_SIZE/2); // Calculate magnitude, outputs q2.14
    arm_max_f32(mag_knock, FFT_SIZE/2, &maxValue, &maxIndex); // Find max magnitude

    // Convert 2.14 to 8 Bits unsigned
    for (i=0; i < sizeof(output_knock); i++)
    {
      uint16_t tmp = (mag_knock[i]/16384);
      if (tmp > 0xFF)
        tmp = 0xFF;
      output_knock[i] = tmp; // 8 bits minus the 2 fractional bits
    }

    sensors_data.knock_freq = settings.knockFreq;

    if (settings.sensorsInput == SENSORS_INPUT_TEST) {
        sensors_data.knock_value = rand16(0, 255);
        continue;
      }

    sensors_data.knock_value = calculateKnockIntensity(
                settings.knockFreq,
                settings.knockRatio,
                FFT_FREQ,
                output_knock,
                sizeof(output_knock));
  }
  return;
}
Ejemplo n.º 20
0
inline void hamming_init()
{
  uint16_t i;
  for(i = 0; i < FRAME_SIZE; ++i)
    Hamming[i] = 0.54-0.46*arm_cos_f32((2*PI*i)/(FRAME_SIZE-1));
}
Ejemplo n.º 21
0
Archivo: main.c Proyecto: johnlaur/PSDR
void populateCoeficients(int bandwidth, int sideband, int offset)
{
	//Chapter 17 of DSP Guide* //TODO: Make a bibliography!

	//1. Take as input, desired filter response in array, both magnitude and phase (it's okay for phase to be zero)
	//	 Looks like magnitude can be any non-negative value. First and last values of Phase must be zero.
	//2. Convert to rectangular form. ***I really wish there was a built in function for this :<
	//3. Run through an inverse FFT.
	//4. Shift
	//5. Truncate
	//6. Window
	//7. Reverse the FFT in preparation for FFT Convolution?

	uint16_t filterKernelLength = 100; //what's a good value? How does it relate to the FFT size?

	//1:
	//sideband: 0 = LSB, 1 = USB, 2 = Both (AM)
	//I think the code below is all wrong. At least for LSB, if the magnitude is zero, then phase doesn't matter, yeah?
	if(sideband > 2) return; //Error
	int i;
	for(i = 0; i < FFT_BUFFER_SIZE; i++)
	{
		switch(sideband)
		{
		case 0:
			if((i > FFT_BUFFER_SIZE - (offset + bandwidth)) && (i < FFT_BUFFER_SIZE - offset))
				fftFilterCoeficient[i] = 1;
			else
				fftFilterCoeficient[i] = 0;
			break;
		case 1:
			if((i > offset) && (i < offset + bandwidth))
				fftFilterCoeficient[i] = 1;
			else
				fftFilterCoeficient[i] = 0;
			break;
		case 2:
			if(((i > FFT_BUFFER_SIZE - (offset + bandwidth)) && (i < FFT_BUFFER_SIZE - offset))
					|| ((i > offset) && (i < offset + bandwidth)))
				fftFilterCoeficient[i] = 1;
			else
				fftFilterCoeficient[i] = 0;
			break;
		}
	}
	fftFilterCoeficient[FFT_BUFFER_SIZE / 2] = 0;
	fftFilterCoeficient[FFT_BUFFER_SIZE - 1] = 0;

	//return; //Skipping all the later stuff doesn't seem to make a huge difference yet...

	//2:
//	float x, y;
//	for(i = 0; i < FFT_SIZE; i++)
//	{
//		polarToRect(fftFilterCoeficient[i], fftFilterCoeficient[FFT_BUFFER_SIZE - 1 - i], &x, &y);
//		fftFilterCoeficient[i] = x;
//		fftFilterCoeficient[FFT_BUFFER_SIZE - 1 - i] = y;
//	}

	//3:
	arm_cfft_radix4_instance_f32 fft_co;
	arm_cfft_radix4_init_f32(&fft_co, FFT_SIZE, 1, 1);
	arm_cfft_radix4_f32(&fft_co, fftFilterCoeficient);

	//4:
	int index;


	for (i = 0; i < FFT_BUFFER_SIZE; i++)
	{
		index = i + filterKernelLength/2;
		if(index > FFT_BUFFER_SIZE - 1) index = index - FFT_BUFFER_SIZE;
		filterTemp[index] = fftFilterCoeficient[i];
	}

	for(i = 0; i < FFT_BUFFER_SIZE; i++)
	{
		fftFilterCoeficient[i] = filterTemp[i];
	}

	//5 & 6:
	for(i = 0; i < FFT_BUFFER_SIZE; i++)
	{
		if(i <= filterKernelLength) fftFilterCoeficient[i] =
				fftFilterCoeficient[i] * (0.54 - 0.46 * arm_cos_f32(2.0 * 3.14159265 * i / filterKernelLength));
		if(i > filterKernelLength) fftFilterCoeficient[i] = 0;
	}

//	arm_cfft_radix4_instance_f32 fft_co;
	arm_cfft_radix4_init_f32(&fft_co, FFT_SIZE, 0, 1);
	arm_cfft_radix4_f32(&fft_co, fftFilterCoeficient);


//	for(i = 0; i < FFT_SIZE; i++)
//	{
//		filterTemp[i] = fftFilterCoeficient[i * 2];
//		filterTemp[FFT_BUFFER_SIZE - 1 - i] = fftFilterCoeficient[i * 2 + 1];
//	}
//
//	for(i = 0; i < FFT_BUFFER_SIZE; i++)
//	{
//		fftFilterCoeficient[i] = filterTemp[i];
//	}
}
Ejemplo n.º 22
0
Archivo: main.c Proyecto: johnlaur/PSDR
void polarToRect(float m, float a, float32_t* x, float32_t* y)
{
	*y = m * arm_sin_f32(a);
	*x = m * arm_cos_f32(a);
}
void correct_sensor()
{
	float Ellipse[5] = {0};
#define MovegAveFIFO_Size 250

	switch (SensorMode) {

	/************************** Mode_CorrectGyr **************************************/
	case Mode_GyrCorrect:
		/* Simple Moving Average */
		Gyr.X = (s16)MoveAve_SMA(Gyr.X, GYR_FIFO[0], MovegAveFIFO_Size);
		Gyr.Y = (s16)MoveAve_SMA(Gyr.Y, GYR_FIFO[1], MovegAveFIFO_Size);
		Gyr.Z = (s16)MoveAve_SMA(Gyr.Z, GYR_FIFO[2], MovegAveFIFO_Size);

		Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料

		if (Correction_Time == SampleRateFreg) {
			Gyr.OffsetX += (Gyr.X - GYR_X_OFFSET);  // 角速度為 0dps
			Gyr.OffsetY += (Gyr.Y - GYR_Y_OFFSET);  // 角速度為 0dps
			Gyr.OffsetZ += (Gyr.Z - GYR_Z_OFFSET);  // 角速度為 0dps

			Correction_Time = 0;
			SensorMode = Mode_AccCorrect;
		}

		break;

	/************************** Mode_CorrectAcc **************************************/
	case Mode_AccCorrect:
		/* Simple Moving Average */
		Acc.X = (s16)MoveAve_SMA(Acc.X, ACC_FIFO[0], MovegAveFIFO_Size);
		Acc.Y = (s16)MoveAve_SMA(Acc.Y, ACC_FIFO[1], MovegAveFIFO_Size);
		Acc.Z = (s16)MoveAve_SMA(Acc.Z, ACC_FIFO[2], MovegAveFIFO_Size);

		Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料

		if (Correction_Time == SampleRateFreg) {
			Acc.OffsetX += (Acc.X - ACC_X_OFFSET);  // 重力加速度為 0g
			Acc.OffsetY += (Acc.Y - ACC_Y_OFFSET);  // 重力加速度為 0g
			Acc.OffsetZ += (Acc.Z - ACC_Z_OFFSET);  // 重力加速度為 1g

			Correction_Time = 0;
			SensorMode = Mode_Quaternion; // Mode_MagCorrect;
		}

		break;

		/************************** Mode_CorrectMag **************************************/
#define MagCorrect_Ave    100
#define MagCorrect_Delay  600   // DelayTime : SampleRate * 600

	case Mode_MagCorrect:
		Correction_Time++;

		switch ((u16)(Correction_Time / MagCorrect_Delay)) {
		case 0:

			MagDataX[0] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[0] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 1:

			MagDataX[1] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[1] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 2:

			MagDataX[2] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[2] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 3:

			MagDataX[3] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[3] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 4:

			MagDataX[4] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[4] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 5:

			MagDataX[5] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[5] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 6:

			MagDataX[6] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[6] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 7:

			MagDataX[7] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[7] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		default:

			EllipseFitting(Ellipse, MagDataX, MagDataY, 8);
			Mag.EllipseSita = Ellipse[0];
			Mag.EllipseX0   = Ellipse[1];
			Mag.EllipseY0   = Ellipse[2];
			Mag.EllipseA    = Ellipse[3];
			Mag.EllipseB    = Ellipse[4];

			Correction_Time = 0;
			SensorMode = Mode_Quaternion;
			break;
		}

		break;

	/************************** Algorithm Mode **************************************/
	case Mode_Quaternion:
		/* To Physical */
		Acc.TrueX = Acc.X * MPU9150A_4g;      // g/LSB
		Acc.TrueY = Acc.Y * MPU9150A_4g;      // g/LSB
		Acc.TrueZ = Acc.Z * MPU9150A_4g;      // g/LSB
		Gyr.TrueX = Gyr.X * MPU9150G_2000dps; // dps/LSB
		Gyr.TrueY = Gyr.Y * MPU9150G_2000dps; // dps/LSB
		Gyr.TrueZ = Gyr.Z * MPU9150G_2000dps; // dps/LSB
		Mag.TrueX = Mag.X * MPU9150M_1200uT;  // uT/LSB
		Mag.TrueY = Mag.Y * MPU9150M_1200uT;  // uT/LSB
		Mag.TrueZ = Mag.Z * MPU9150M_1200uT;  // uT/LSB
		Temp.TrueT = Temp.T * MPU9150T_85degC; // degC/LSB

		Ellipse[3] = (Mag.X * arm_cos_f32(Mag.EllipseSita) + Mag.Y * arm_sin_f32(Mag.EllipseSita)) / Mag.EllipseB;
		Ellipse[4] = (-Mag.X * arm_sin_f32(Mag.EllipseSita) + Mag.Y * arm_cos_f32(Mag.EllipseSita)) / Mag.EllipseA;

		AngE.Pitch = toDeg(atan2f(Acc.TrueY, Acc.TrueZ));
		AngE.Roll  = toDeg(-asinf(Acc.TrueX));
		AngE.Yaw   = toDeg(atan2f(Ellipse[3], Ellipse[4])) + 180.0f;

		Quaternion_ToNumQ(&NumQ, &AngE);

		SensorMode = Mode_Algorithm;
		break;
	}

}
Ejemplo n.º 24
0
/*=====================================================================================================*/
void AHRS_Update(void)
{
	float tempX = 0, tempY = 0;
	float Normalize;
	float gx, gy, gz;
// float hx, hy, hz;
// float wx, wy, wz;
// float bx, bz;
	float ErrX, ErrY, ErrZ;
	float AccX, AccY, AccZ;
	float GyrX, GyrY, GyrZ;
// float MegX, MegY, MegZ;
	float /*Mq11, Mq12, */Mq13,/* Mq21, Mq22, */Mq23,/* Mq31, Mq32, */Mq33;

	static float AngZ_Temp = 0.0f;
	static float exInt = 0.0f, eyInt = 0.0f, ezInt = 0.0f;

//   Mq11 = NumQ.q0*NumQ.q0 + NumQ.q1*NumQ.q1 - NumQ.q2*NumQ.q2 - NumQ.q3*NumQ.q3;
//   Mq12 = 2.0f*(NumQ.q1*NumQ.q2 + NumQ.q0*NumQ.q3);
	Mq13 = 2.0f * (NumQ.q1 * NumQ.q3 - NumQ.q0 * NumQ.q2);
//   Mq21 = 2.0f*(NumQ.q1*NumQ.q2 - NumQ.q0*NumQ.q3);
//   Mq22 = NumQ.q0*NumQ.q0 - NumQ.q1*NumQ.q1 + NumQ.q2*NumQ.q2 - NumQ.q3*NumQ.q3;
	Mq23 = 2.0f * (NumQ.q0 * NumQ.q1 + NumQ.q2 * NumQ.q3);
//   Mq31 = 2.0f*(NumQ.q0*NumQ.q2 + NumQ.q1*NumQ.q3);
//   Mq32 = 2.0f*(NumQ.q2*NumQ.q3 - NumQ.q0*NumQ.q1);
	Mq33 = NumQ.q0 * NumQ.q0 - NumQ.q1 * NumQ.q1 - NumQ.q2 * NumQ.q2 + NumQ.q3 * NumQ.q3;

	Normalize = invSqrtf(squa(Acc.TrueX) + squa(Acc.TrueY) + squa(Acc.TrueZ));
	AccX = Acc.TrueX * Normalize;
	AccY = Acc.TrueY * Normalize;
	AccZ = Acc.TrueZ * Normalize;

// Normalize = invSqrtf(squa(Meg.TrueX) + squa(Meg.TrueY) + squa(Meg.TrueZ));
// MegX = Meg.TrueX*Normalize;
// MegY = Meg.TrueY*Normalize;
// MegZ = Meg.TrueZ*Normalize;

	gx = Mq13;
	gy = Mq23;
	gz = Mq33;

// hx = MegX*Mq11 + MegY*Mq21 + MegZ*Mq31;
// hy = MegX*Mq12 + MegY*Mq22 + MegZ*Mq32;
// hz = MegX*Mq13 + MegY*Mq23 + MegZ*Mq33;

// bx = sqrtf(squa(hx) + squa(hy));
// bz = hz;

// wx = bx*Mq11 + bz*Mq13;
// wy = bx*Mq21 + bz*Mq23;
// wz = bx*Mq31 + bz*Mq33;

	ErrX = (AccY * gz - AccZ * gy)/* + (MegY*wz - MegZ*wy)*/;
	ErrY = (AccZ * gx - AccX * gz)/* + (MegZ*wx - MegX*wz)*/;
	ErrZ = (AccX * gy - AccY * gx)/* + (MegX*wy - MegY*wx)*/;

	exInt = exInt + ErrX * Ki;
	eyInt = eyInt + ErrY * Ki;
	ezInt = ezInt + ErrZ * Ki;

	GyrX = toRad(Gyr.TrueX);
	GyrY = toRad(Gyr.TrueY);
	GyrZ = toRad(Gyr.TrueZ);

	GyrX = GyrX + Kp * ErrX + exInt;
	GyrY = GyrY + Kp * ErrY + eyInt;
	GyrZ = GyrZ + Kp * ErrZ + ezInt;

	Quaternion_RungeKutta(&NumQ, GyrX, GyrY, GyrZ, SampleRateHelf);
	Quaternion_Normalize(&NumQ);
	Quaternion_ToAngE(&NumQ, &AngE);

	tempX    = (Mag.X * arm_cos_f32(Mag.EllipseSita) + Mag.Y * arm_sin_f32(Mag.EllipseSita)) / Mag.EllipseB;
	tempY    = (-Mag.X * arm_sin_f32(Mag.EllipseSita) + Mag.Y * arm_cos_f32(Mag.EllipseSita)) / Mag.EllipseA;
	AngE.Yaw = atan2f(tempX, tempY);

	AngE.Pitch = toDeg(AngE.Pitch);
	AngE.Roll  = toDeg(AngE.Roll);
	AngE.Yaw   = toDeg(AngE.Yaw) + 180.0f;

	/* 互補濾波 Complementary Filter */
#define CF_A 0.9f
#define CF_B 0.1f
	AngZ_Temp = AngZ_Temp + GyrZ * SampleRate;
	AngZ_Temp = CF_A * AngZ_Temp + CF_B * AngE.Yaw;

	if (AngZ_Temp > 360.0f)
		AngE.Yaw = AngZ_Temp - 360.0f;
	else if (AngZ_Temp < 0.0f)
		AngE.Yaw = AngZ_Temp + 360.0f;
	else
		AngE.Yaw = AngZ_Temp;
}
Ejemplo n.º 25
0
/*=====================================================================================================*/
void EllipseFitting(float *Ans, volatile s16 *MagDataX, volatile s16 *MagDataY, u8 Num)
{
	s8 i, j, k;
	float temp, temp1, temp2;
	float tempArrX[8] = {0};
	float tempArrY[8] = {0};

	float MAG_X1Y0 = 0.0f;
	float MAG_X2Y0 = 0.0f;
	float MAG_X3Y0 = 0.0f;
	float MAG_X0Y1 = 0.0f;
	float MAG_X0Y2 = 0.0f;
	float MAG_X0Y3 = 0.0f;
	float MAG_X0Y4 = 0.0f;
	float MAG_X1Y1 = 0.0f;
	float MAG_X2Y1 = 0.0f;
	float MAG_X1Y2 = 0.0f;
	float MAG_X1Y3 = 0.0f;
	float MAG_X2Y2 = 0.0f;
	float MAG_X3Y1 = 0.0f;

	float MagArr[5][6] = {{0}};

	for (i = 0; i < Num; i++) {
		tempArrX[i] = (float)MagDataX[i] / 1000.0f;
		tempArrY[i] = (float)MagDataY[i] / 1000.0f;
	}

	for (i = 0; i < Num; i++) {
		MAG_X1Y0 += tempArrX[i];
		MAG_X2Y0 += tempArrX[i] * tempArrX[i];
		MAG_X3Y0 += tempArrX[i] * tempArrX[i] * tempArrX[i];
		MAG_X0Y1 += tempArrY[i];
		MAG_X0Y2 += tempArrY[i] * tempArrY[i];
		MAG_X0Y3 += tempArrY[i] * tempArrY[i] * tempArrY[i];
		MAG_X0Y4 += tempArrY[i] * tempArrY[i] * tempArrY[i] * tempArrY[i];
		MAG_X1Y1 += tempArrX[i] * tempArrY[i];
		MAG_X2Y1 += tempArrX[i] * tempArrX[i] * tempArrY[i];
		MAG_X1Y2 += tempArrX[i] * tempArrY[i] * tempArrY[i];
		MAG_X1Y3 += tempArrX[i] * tempArrY[i] * tempArrY[i] * tempArrY[i];
		MAG_X2Y2 += tempArrX[i] * tempArrX[i] * tempArrY[i] * tempArrY[i];
		MAG_X3Y1 += tempArrX[i] * tempArrX[i] * tempArrX[i] * tempArrY[i];
	}

	MagArr[0][0] = MAG_X2Y2;
	MagArr[0][1] = MAG_X1Y3;
	MagArr[0][2] = MAG_X2Y1;
	MagArr[0][3] = MAG_X1Y2;
	MagArr[0][4] = MAG_X1Y1;
	MagArr[0][5] = -MAG_X3Y1;

	MagArr[1][0] = MAG_X1Y3;
	MagArr[1][1] = MAG_X0Y4;
	MagArr[1][2] = MAG_X1Y2;
	MagArr[1][3] = MAG_X0Y3;
	MagArr[1][4] = MAG_X0Y2;
	MagArr[1][5] = -MAG_X2Y2;

	MagArr[2][0] = MAG_X2Y1;
	MagArr[2][1] = MAG_X1Y2;
	MagArr[2][2] = MAG_X2Y0;
	MagArr[2][3] = MAG_X1Y1;
	MagArr[2][4] = MAG_X1Y0;
	MagArr[2][5] = -MAG_X3Y0;

	MagArr[3][0] = MAG_X1Y2;
	MagArr[3][1] = MAG_X0Y3;
	MagArr[3][2] = MAG_X1Y1;
	MagArr[3][3] = MAG_X0Y2;
	MagArr[3][4] = MAG_X0Y1;
	MagArr[3][5] = -MAG_X2Y1;

	MagArr[4][0] = MAG_X1Y1;
	MagArr[4][1] = MAG_X0Y2;
	MagArr[4][2] = MAG_X1Y0;
	MagArr[4][3] = MAG_X0Y1;
	MagArr[4][4] = Num;
	MagArr[4][5] = -MAG_X2Y0;

	for (i = 0; i < 5; i++)
		for (j = i + 1; j < 6; j++)
			for (k = 5; k > i - 1; k--)
				MagArr[j][k] = MagArr[j][k] - MagArr[j][i] / MagArr[i][i] * MagArr[i][k];

	for (i = 0; i < 5; i++) {
		temp = MagArr[i][i];

		for (j = i; j < 6; j++)
			MagArr[i][j] = MagArr[i][j] / temp;
	}

	for (j = 4; j > 0; j--)
		for (i = 0; i < j; i++)
			MagArr[i][5] = MagArr[i][5] - MagArr[i][j] * MagArr[j][5];

	temp = (1.0f - MagArr[1][5]) / MagArr[0][5];
	temp1 = temp + sqrtf(temp * temp + 1.0f);
	Ans[0] = atanf(temp1);	// Theta

	temp = MagArr[0][5] * MagArr[0][5] - 4 * MagArr[1][5];
	Ans[1] = (2.0f * MagArr[1][5] * MagArr[2][5] - MagArr[0][5] * MagArr[3][5]) / temp;	// X0
	Ans[2] = (2.0f * MagArr[3][5] - MagArr[0][5] * MagArr[2][5]) / temp;	    // Y0

	temp = arm_cos_f32(Ans[0]);
	temp2  = (Ans[1] * Ans[1] + MagArr[0][5] * Ans[1] * Ans[2] + MagArr[1][5] * Ans[2] * Ans[2] - MagArr[4][5]) * (temp1 * temp1 * temp1 * temp1 - 1.0f);
	Ans[3] = temp / sqrtf((MagArr[1][5] * temp1 * temp1 - 1) / temp2);	// a
	Ans[4] = temp / sqrtf((temp1 * temp1 - MagArr[1][5]) / temp2); // b

	Ans[1] = Ans[1] * 1000.0f;
	Ans[2] = Ans[2] * 1000.0f;
	Ans[3] = Ans[3] * 1000.0f;
	Ans[4] = Ans[4] * 1000.0f;
}
Ejemplo n.º 26
0
void vMovingControlTask(void *pvParameters)
{
	Position TargetPos;
	Position ExpectPos;
	MoveCmd SendCmd, ReResult;
	float DeltAngle, DeltDistance;
	float XYi[3];
	while (1)
	{
		if (pdTRUE == xQueueReceive(TargetPosQueue, &TargetPos, portMAX_DELAY))
		{
//			printf("get TargetPosQueue\r\n");
			while ((fabs(TargetPos.Angle - CurPos.Angle) > 180 ? 360 - fabs(TargetPos.Angle - CurPos.Angle) : fabs(TargetPos.Angle - CurPos.Angle)) * STEP_ANGLE >= ADJUST_STEP_ANGLE\
				|| sqrt(pow(TargetPos.y - CurPos.y, 2) + pow(TargetPos.x - CurPos.x, 2)) * STEP_METER >= ADJUST_STEP_DIRECT)
			{
//				Debug_printf("CurPos: %f %f %f\r\n", CurPos.Angle, CurPos.x, CurPos.y);
//				Debug_printf("CurPos: %f %f %f\r\n", CurPos.Angle, CurPos.x, CurPos.y);
//				Debug_printf("Compass: %f\r\n", CurAngle);
//				Debug_printf("DAngle: %f\r\n", fabs(TargetPos.Angle - CurPos.Angle) * STEP_ANGLE);
//				Debug_printf("Distance: %f\r\n", sqrt(pow(TargetPos.y - CurPos.y, 2) + pow(TargetPos.x - CurPos.x, 2)) * STEP_METER);
				if (sqrt(pow(TargetPos.y - CurPos.y, 2) + pow(TargetPos.x - CurPos.x, 2)) * STEP_METER >= ADJUST_STEP_DIRECT)
				{
					ExpectPos.Angle = (atan2(TargetPos.y - CurPos.y, TargetPos.x - CurPos.x)/PI)*180;
					
//					printf("ExpectPos.Angle1 : %f\r\n",ExpectPos.Angle);
					ExpectPos.x = CurPos.x;
					ExpectPos.y = CurPos.y;
					DeltAngle = ExpectPos.Angle - CurPos.Angle;
					
//					Debug_printf("DAngle: %f\r\n", DeltAngle);
					if (DeltAngle > 180)
					{
						DeltAngle = DeltAngle - 360;
					}                     
					if(DeltAngle < -180)
					{
						DeltAngle = 360 + DeltAngle;
					}
					if (DeltAngle < 0)
					{
						SendCmd.direct = turnright;
					}
					else
					{
						SendCmd.direct = turnleft;
					}
					SendCmd.step = fabs(DeltAngle) * STEP_ANGLE;
//					vTaskDelay(1000);
					xQueueSend(MoveCmdQueue, &SendCmd, portMAX_DELAY);
					if (pdTRUE == xQueueReceive(MoveRsultQueue, &ReResult, portMAX_DELAY))
					{
//						Debug_printf("get MoveRsultQueue\r\n");
						//CurPos = ExpectPos;
						if (SendCmd.direct == turnright)
						{
							CurPos.Angle = CurPos.Angle - ((float)ReResult.step) / STEP_ANGLE;
						}
						if (SendCmd.direct == turnleft)
						{
							CurPos.Angle = CurPos.Angle + ((float)ReResult.step) / STEP_ANGLE;
						}
						
						if (CurPos.Angle > 180)
						{
							CurPos.Angle = CurPos.Angle - 360;
						}
						if (CurPos.Angle < -180)
						{
							CurPos.Angle = CurPos.Angle + 360;
						}
						//??
						//????????;
						//printf("CurPos.Angle: %f\r\n", CurPos.Angle);
						if (ANGLE_CORRECTION_THRESHOLD < fabs(CurPos.Angle - CurAngle))
						{
							CurPos.Angle = CurAngle;
						}
						//printf("FIXED CurPos.Angle: %f\r\n", CurPos.Angle);
						if(pdTRUE == xQueueReceive(PositionUpdatekQueue, XYi, 2))
						{
							//????????;
							switch (GlobleCmdDir)
							{
								case forward:
									XYi[0] = XYi[0] + ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_cos_f32((CurPos.Angle / 180) * PI);
							    XYi[1] = XYi[1] + ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_sin_f32((CurPos.Angle / 180) * PI);
									break;
								case backward:
									XYi[0] = XYi[0] - ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_cos_f32((CurPos.Angle / 180) * PI);
							    XYi[1] = XYi[1] - ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_sin_f32((CurPos.Angle / 180) * PI);
									break;
								case turnright:			
									break;
								case turnleft:
									break;
								default:
									break;		
							}
							CurPos.x = XYi[0];
							CurPos.y = XYi[1];
						}
						if(pdTRUE == xSemaphoreTake(FoundTargetSyn, 1))
						{
//							Debug_printf("I am IN 1\r\n");
							TargetPos = CurPos;
						}
					}
				}
				else
				{
					ExpectPos.Angle = TargetPos.Angle;
					
//					printf("ExpectPos.Angle2 : %f\r\n",ExpectPos.Angle);
					ExpectPos.x = CurPos.x;
					ExpectPos.y = CurPos.y;
					DeltAngle = ExpectPos.Angle - CurPos.Angle;
					
					
					if (DeltAngle > 180)
					{
						DeltAngle = DeltAngle - 360;
					}                     
					if(DeltAngle < -180)
					{
						DeltAngle = 360 + DeltAngle;
					}
					if (DeltAngle < 0)
					{
						SendCmd.direct = turnright;
					}
					else
					{
						SendCmd.direct = turnleft;
					}
					SendCmd.step = fabs(DeltAngle) * STEP_ANGLE;
//					vTaskDelay(1000);
					xQueueSend(MoveCmdQueue, &SendCmd, portMAX_DELAY);
					if (pdTRUE == xQueueReceive(MoveRsultQueue, &ReResult, portMAX_DELAY))
					{
						//CurPos = ExpectPos;MoveRsultQueue
//						Debug_printf("get MoveRsultQueue\r\n");
						if (SendCmd.direct == turnright)
						{
							CurPos.Angle = CurPos.Angle - ((float)ReResult.step) / STEP_ANGLE;
						}
						if (SendCmd.direct == turnleft)
						{
							CurPos.Angle = CurPos.Angle + ((float)ReResult.step) / STEP_ANGLE;
						}
						
						if (CurPos.Angle > 180)
						{
							CurPos.Angle = CurPos.Angle - 360;
						}
						if (CurPos.Angle < -180)
						{
							CurPos.Angle = CurPos.Angle + 360;
						}
						//??
						//????????;
						//printf(" else CurPos.Angle: %f\r\n", CurPos.Angle);
						if (ANGLE_CORRECTION_THRESHOLD < fabs(CurPos.Angle - CurAngle))
						{
							CurPos.Angle = CurAngle;
						}
						//printf("else FIXED CurPos.Angle: %f\r\n", CurPos.Angle);
						if(pdTRUE == xQueueReceive(PositionUpdatekQueue, XYi, 2))
						{
							//????????;
							switch (GlobleCmdDir)
							{
								case forward:
									XYi[0] = XYi[0] + ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_cos_f32((CurPos.Angle / 180) * PI);
							    XYi[1] = XYi[1] + ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_sin_f32((CurPos.Angle / 180) * PI);
									break;
								case backward:
									XYi[0] = XYi[0] - ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_cos_f32((CurPos.Angle / 180) * PI);
							    XYi[1] = XYi[1] - ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_sin_f32((CurPos.Angle / 180) * PI);
									break;
								case turnright:			
									break;
								case turnleft:
									break;
								default:
									break;		
							}
							CurPos.x = XYi[0];
							CurPos.y = XYi[1];
						}
						if(pdTRUE == xSemaphoreTake(FoundTargetSyn, 100))
						{
//							Debug_printf("I am IN 2\r\n");
							TargetPos = CurPos;
						}
					}
				}
				
				if ((fabs(ExpectPos.Angle - CurPos.Angle) > 180 ? 360 - fabs(ExpectPos.Angle - CurPos.Angle) : fabs(ExpectPos.Angle - CurPos.Angle)) * STEP_ANGLE < ADJUST_STEP_ANGLE\
					&& sqrt(pow(TargetPos.y - CurPos.y, 2) + pow(TargetPos.x - CurPos.x, 2)) * STEP_METER >= ADJUST_STEP_DIRECT)
				{
					ExpectPos.x = TargetPos.x;
					ExpectPos.y = TargetPos.y;
					DeltDistance = sqrt(pow(ExpectPos.y - CurPos.y, 2) + pow(ExpectPos.x - CurPos.x, 2));
					SendCmd.direct = forward;
					SendCmd.step = DeltDistance * STEP_METER;
//					vTaskDelay(1000);
//          Debug_printf("return1\r\n");
					xQueueSend(MoveCmdQueue, &SendCmd, portMAX_DELAY);
					
					if (pdTRUE == xQueueReceive(MoveRsultQueue, &ReResult, portMAX_DELAY))
					{
//						Debug_printf("return2\r\n");
						//CurPos = ExpectPos;
//						Debug_printf("get MoveRsultQueue\r\n");
						CurPos.x = CurPos.x + (ReResult.step / STEP_METER) * arm_cos_f32((CurPos.Angle / 180) * PI);
						CurPos.y = CurPos.y + (ReResult.step / STEP_METER) * arm_sin_f32((CurPos.Angle / 180) * PI);
						
						//??
						//????????;
						if (ANGLE_CORRECTION_THRESHOLD < fabs(CurPos.Angle - CurAngle))
						{
							CurPos.Angle = CurAngle;
						}
						if(pdTRUE == xQueueReceive(PositionUpdatekQueue, XYi, 2))
						{
							//????????;
							switch (GlobleCmdDir)
							{
								case forward:
									XYi[0] = XYi[0] + ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_cos_f32((CurPos.Angle / 180) * PI);
							    XYi[1] = XYi[1] + ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_sin_f32((CurPos.Angle / 180) * PI);
									break;
								case backward:
									XYi[0] = XYi[0] - ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_cos_f32((CurPos.Angle / 180) * PI);
							    XYi[1] = XYi[1] - ((float)(ReResult.step - XYi[2]) / STEP_METER) * arm_sin_f32((CurPos.Angle / 180) * PI);
									break;
								case turnright:			
									break;
								case turnleft:
									break;
								default:
									break;		
							}
							CurPos.x = XYi[0];
							CurPos.y = XYi[1];
						}
						if(pdTRUE == xSemaphoreTake(FoundTargetSyn, 1))
						{
//							Debug_printf("I am IN 3\r\n");
							TargetPos = CurPos;
						}
//						Debug_printf("return3\r\n");
					}
				}
				
			}
//			Debug_printf("TargetPos: %f %f %f\r\n", CurPos.Angle, CurPos.x, CurPos.y);
//			Debug_printf("CurPos: %f %f %f\r\n", CurPos.Angle, CurPos.x, CurPos.y);
//			Debug_printf("Compass: %f\r\n", CurAngle);
			xSemaphoreGive(MoveComplete);
//			printf("Complete1\r\n");
		}
	}
}
/* Cálculos do cos utilizando as funções disponíveis nas funções de DSP do arm. */
float f_cos(float angle) {
	return arm_cos_f32(angle);
}
/* Cálculos do tan utilizando as funções disponíveis nas funções de DSP do arm. */
float f_tan(float angle) {
	return (arm_sin_f32(angle)/arm_cos_f32(angle));
}
/* Cálculos do sec utilizando as funções disponíveis nas funções de DSP do arm. */
float f_sec(float angle) {
	return (1/arm_cos_f32(angle));
}
Ejemplo n.º 30
0
/*=====================================================================================================*/
void SysTick_Handler( void )
{
  u8 IMU_Buf[20] = {0};

  u16 Final_M1 = 0;
  u16 Final_M2 = 0;
  u16 Final_M3 = 0;
  u16 Final_M4 = 0;

  s16 Thr = 0, Pitch = 0, Roll = 0, Yaw = 0;

  float Ellipse[5] = {0};

  static u8  BaroCnt = 0;

  static s16 ACC_FIFO[3][256] = {0};
  static s16 GYR_FIFO[3][256] = {0};
  static s16 MAG_FIFO[3][256] = {0};

  static s16 MagDataX[8] = {0};
  static s16 MagDataY[8] = {0};

  static u16 Correction_Time = 0;

  /* Time Count */
  SysTick_Cnt++;
  if(SysTick_Cnt == SampleRateFreg) {
    SysTick_Cnt = 0;
    Time_Sec++;
    if(Time_Sec == 60) {	// 0~59
      Time_Sec = 0;
      Time_Min++;
      if(Time_Sec == 60)
      Time_Min = 0;
    }
  }

  /* 400Hz, Read Sensor ( Accelerometer, Gyroscope, Magnetometer ) */
  MPU9150_Read(IMU_Buf);

  /* 100Hz, Read Barometer */
  BaroCnt++;
  if(BaroCnt == 4) {
    MS5611_Read(&Baro, MS5611_D1_OSR_4096);
    BaroCnt = 0;
  }

  Acc.X  = (s16)((IMU_Buf[0]  << 8) | IMU_Buf[1]);
  Acc.Y  = (s16)((IMU_Buf[2]  << 8) | IMU_Buf[3]);
  Acc.Z  = (s16)((IMU_Buf[4]  << 8) | IMU_Buf[5]);
  Temp.T = (s16)((IMU_Buf[6]  << 8) | IMU_Buf[7]);
  Gyr.X  = (s16)((IMU_Buf[8]  << 8) | IMU_Buf[9]);
  Gyr.Y  = (s16)((IMU_Buf[10] << 8) | IMU_Buf[11]);
  Gyr.Z  = (s16)((IMU_Buf[12] << 8) | IMU_Buf[13]);
  Mag.X  = (s16)((IMU_Buf[15] << 8) | IMU_Buf[14]);
  Mag.Y  = (s16)((IMU_Buf[17] << 8) | IMU_Buf[16]);
  Mag.Z  = (s16)((IMU_Buf[19] << 8) | IMU_Buf[18]);

  /* Offset */
  Acc.X -= Acc.OffsetX;
  Acc.Y -= Acc.OffsetY;
  Acc.Z -= Acc.OffsetZ;
  Gyr.X -= Gyr.OffsetX;
  Gyr.Y -= Gyr.OffsetY;
  Gyr.Z -= Gyr.OffsetZ;
  Mag.X *= Mag.AdjustX;
  Mag.Y *= Mag.AdjustY;
  Mag.Z *= Mag.AdjustZ;

  #define MovegAveFIFO_Size 250
  switch(SensorMode) {

  /************************** Mode_CorrectGyr **************************************/
    case Mode_GyrCorrect:
      LED_R = !LED_R;
      /* Simple Moving Average */
      Gyr.X = (s16)MoveAve_SMA(Gyr.X, GYR_FIFO[0], MovegAveFIFO_Size);
      Gyr.Y = (s16)MoveAve_SMA(Gyr.Y, GYR_FIFO[1], MovegAveFIFO_Size);
      Gyr.Z = (s16)MoveAve_SMA(Gyr.Z, GYR_FIFO[2], MovegAveFIFO_Size);

      Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料
      if(Correction_Time == 400) {
        Gyr.OffsetX += (Gyr.X - GYR_X_OFFSET);  // 角速度為 0dps
        Gyr.OffsetY += (Gyr.Y - GYR_Y_OFFSET);  // 角速度為 0dps
        Gyr.OffsetZ += (Gyr.Z - GYR_Z_OFFSET);  // 角速度為 0dps

        Correction_Time = 0;
        SensorMode = Mode_MagCorrect; // Mode_AccCorrect;
      }
      break;
 
  /************************** Mode_CorrectAcc **************************************/
    case Mode_AccCorrect:
      LED_R = ~LED_R;
      /* Simple Moving Average */
      Acc.X = (s16)MoveAve_SMA(Acc.X, ACC_FIFO[0], MovegAveFIFO_Size);
      Acc.Y = (s16)MoveAve_SMA(Acc.Y, ACC_FIFO[1], MovegAveFIFO_Size);
      Acc.Z = (s16)MoveAve_SMA(Acc.Z, ACC_FIFO[2], MovegAveFIFO_Size);

      Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料
      if(Correction_Time == 400) {
        Acc.OffsetX += (Acc.X - ACC_X_OFFSET);  // 重力加速度為 0g
        Acc.OffsetY += (Acc.Y - ACC_Y_OFFSET);  // 重力加速度為 0g
        Acc.OffsetZ += (Acc.Z - ACC_Z_OFFSET);  // 重力加速度為 1g

        Correction_Time = 0;
        SensorMode = Mode_Quaternion; // Mode_MagCorrect;
      }
      break;

  /************************** Mode_CorrectMag **************************************/
    #define MagCorrect_Ave    100
    #define MagCorrect_Delay  600   // 2.5ms * 600 = 1.5s
    case Mode_MagCorrect:
      LED_R = !LED_R;
      Correction_Time++;
      switch((u16)(Correction_Time/MagCorrect_Delay)) {
        case 0:
          LED_B = 0;
          MagDataX[0] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[0] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 1:
          LED_B = 1;
          MagDataX[1] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[1] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 2:
          LED_B = 0;
          MagDataX[2] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[2] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 3:
          LED_B = 1;
          MagDataX[3] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[3] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 4:
          LED_B = 0;
          MagDataX[4] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[4] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 5:
          LED_B = 1;
          MagDataX[5] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[5] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 6:
          LED_B = 0;
          MagDataX[6] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[6] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 7:
          LED_B = 1;
          MagDataX[7] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[7] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        default:
          LED_B = 1;
          EllipseFitting(Ellipse, MagDataX, MagDataY, 8);
          Mag.EllipseSita = Ellipse[0];
          Mag.EllipseX0   = Ellipse[1];
          Mag.EllipseY0   = Ellipse[2];
          Mag.EllipseA    = Ellipse[3];
          Mag.EllipseB    = Ellipse[4];

          Correction_Time = 0;
          SensorMode = Mode_Quaternion;
          break;
      }
      break;

  /************************** Algorithm Mode **************************************/
    case Mode_Quaternion:
      LED_R = !LED_R;

      /* To Physical */
      Acc.TrueX = Acc.X*MPU9150A_4g;        // g/LSB
      Acc.TrueY = Acc.Y*MPU9150A_4g;        // g/LSB
      Acc.TrueZ = Acc.Z*MPU9150A_4g;        // g/LSB
      Gyr.TrueX = Gyr.X*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueY = Gyr.Y*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueZ = Gyr.Z*MPU9150G_2000dps;   // dps/LSB
      Mag.TrueX = Mag.X*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueY = Mag.Y*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueZ = Mag.Z*MPU9150M_1200uT;    // uT/LSB
      Temp.TrueT = Temp.T*MPU9150T_85degC;  // degC/LSB

      Ellipse[3] = ( Mag.X*arm_cos_f32(Mag.EllipseSita)+Mag.Y*arm_sin_f32(Mag.EllipseSita))/Mag.EllipseB;
      Ellipse[4] = (-Mag.X*arm_sin_f32(Mag.EllipseSita)+Mag.Y*arm_cos_f32(Mag.EllipseSita))/Mag.EllipseA;

      AngE.Pitch = toDeg(atan2f(Acc.TrueY, Acc.TrueZ));
      AngE.Roll  = toDeg(-asinf(Acc.TrueX));
      AngE.Yaw   = toDeg(atan2f(Ellipse[3], Ellipse[4]))+180.0f;

      Quaternion_ToNumQ(&NumQ, &AngE);

      SensorMode = Mode_Algorithm;
      break;

  /************************** Algorithm Mode ****************************************/
    case Mode_Algorithm:

      /* 加權移動平均法 Weighted Moving Average */
      Acc.X = (s16)MoveAve_WMA(Acc.X, ACC_FIFO[0], 8);
      Acc.Y = (s16)MoveAve_WMA(Acc.Y, ACC_FIFO[1], 8);
      Acc.Z = (s16)MoveAve_WMA(Acc.Z, ACC_FIFO[2], 8);
      Gyr.X = (s16)MoveAve_WMA(Gyr.X, GYR_FIFO[0], 8);
      Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, GYR_FIFO[1], 8);
      Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, GYR_FIFO[2], 8);
      Mag.X = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], 64);
      Mag.Y = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], 64);
      Mag.Z = (s16)MoveAve_WMA(Mag.Z, MAG_FIFO[2], 64);

      /* To Physical */
      Acc.TrueX = Acc.X*MPU9150A_4g;        // g/LSB
      Acc.TrueY = Acc.Y*MPU9150A_4g;        // g/LSB
      Acc.TrueZ = Acc.Z*MPU9150A_4g;        // g/LSB
      Gyr.TrueX = Gyr.X*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueY = Gyr.Y*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueZ = Gyr.Z*MPU9150G_2000dps;   // dps/LSB
      Mag.TrueX = Mag.X*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueY = Mag.Y*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueZ = Mag.Z*MPU9150M_1200uT;    // uT/LSB
      Temp.TrueT = Temp.T*MPU9150T_85degC;  // degC/LSB

      /* Get Attitude Angle */
      AHRS_Update();

//      if(KEYL_U == 0)	{	PID_Roll.Kp += 0.001f;	PID_Pitch.Kp += 0.001f;  }
//      if(KEYL_L == 0)	{	PID_Roll.Kp -= 0.001f;	PID_Pitch.Kp -= 0.001f;  }
//      if(KEYL_R == 0)	{	PID_Roll.Ki += 0.0001f;	PID_Pitch.Ki += 0.0001f; }
//      if(KEYL_D == 0)	{	PID_Roll.Ki -= 0.0001f;	PID_Pitch.Ki -= 0.0001f; }
//      if(KEYR_R == 0)	{	PID_Roll.Kd += 0.0001f;	PID_Pitch.Kd += 0.0001f; }
//      if(KEYR_D == 0)	{	PID_Roll.Kd -= 0.0001f;	PID_Pitch.Kd -= 0.0001f; }
//      if(KEYR_L == 0)	{	PID_Roll.SumErr = 0.0f;	PID_Pitch.SumErr = 0.0f; }
//      if(KEYL_U == 0)	{	PID_Yaw.Kp += 0.001f;    }
//      if(KEYL_L == 0)	{	PID_Yaw.Kp -= 0.001f;    }
//      if(KEYL_R == 0)	{	PID_Yaw.Ki += 0.001f;	 }
//      if(KEYL_D == 0)	{	PID_Yaw.Ki -= 0.001f;	 }
//      if(KEYR_R == 0)	{	PID_Yaw.Kd += 0.0001f;	 }
//      if(KEYR_D == 0)	{	PID_Yaw.Kd -= 0.0001f;	 }
//      if(KEYR_L == 0)	{	PID_Roll.SumErr = 0.0f;	 }

      /* Get ZeroErr */
      PID_Pitch.ZeroErr = (float)((s16)Exp_Pitch/4.5f);
      PID_Roll.ZeroErr  = (float)((s16)Exp_Roll/4.5f);
      PID_Yaw.ZeroErr   = (float)((s16)Exp_Yaw)+180.0f;

      /* PID */
      Roll  = (s16)PID_AHRS_Cal(&PID_Roll,   AngE.Roll,  Gyr.TrueX);
      Pitch = (s16)PID_AHRS_Cal(&PID_Pitch,  AngE.Pitch, Gyr.TrueY);
//      Yaw   = (s16)PID_AHRS_CalYaw(&PID_Yaw, AngE.Yaw,   Gyr.TrueZ);
      Yaw   = (s16)(PID_Yaw.Kd*Gyr.TrueZ);
      Thr   = (s16)Exp_Thr;

      /* Motor Ctrl */
      Final_M1 = PWM_M1 + Thr + Pitch + Roll + Yaw;
      Final_M2 = PWM_M2 + Thr - Pitch + Roll - Yaw;
      Final_M3 = PWM_M3 + Thr - Pitch - Roll + Yaw;
      Final_M4 = PWM_M4 + Thr + Pitch - Roll - Yaw;

      /* Check Connection */
      #define NoSignal 1  // 1 sec
      if(KEYR_L == 0)
        Motor_Control(PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN);
      else if(((Time_Sec-RecvTime_Sec)>NoSignal) || ((Time_Sec-RecvTime_Sec)<-NoSignal))
        Motor_Control(PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN);
      else
        Motor_Control(Final_M1, Final_M2, Final_M3, Final_M4);

      /* DeBug */
      Tmp_PID_KP = PID_Yaw.Kp*1000;
      Tmp_PID_KI = PID_Yaw.Ki*1000;
      Tmp_PID_KD = PID_Yaw.Kd*1000;
      Tmp_PID_Pitch = Yaw;

      break;
  }
}