int InputEventSensor::activate(int handle, int enabled) {
        static int activated = 0;
        int result;

        if (handle != device.getHandle()) {
                log_message(CRITICAL,"%s: line: %d: %s handle not match! handle: %d required handle: %d",
                     __FUNCTION__, __LINE__, data.name.c_str(), device.getHandle(), handle);
                return -1;
        }

        enabled = enabled == 0 ? 0 : 1;

        if (Calibration != NULL) {
                if (enabled && !activated)
                        Calibration(&event, READ_DATA, data.calibrationFile.c_str());
                else if (!enabled && activated)
                        Calibration(&event, STORE_DATA, data.calibrationFile.c_str());
        }
        result =writeToFile(data.activateInterface, handle, static_cast<int64_t>(enabled));

        if (DriverCalibration != NULL && enabled != 0 && result == 0 && activated == 0)
                DriverCalibration(&event, CALIBRATION_DATA, data.driverCalibrationFile.c_str(), data.driverCalibrationInterface.c_str());

        activated = enabled;

        return result;
}
//********************************************************************
// Main Functions
//********************************************************************
void main(void) { //Main function
    Sys_Init(); // initialize board
    putchar(' '); //the quotes in this line may not format correctly
    Port_Init();//Init ports
    XBR0_Init();//init xbro
    PCA_Init();//init pca
    SMB_Init();//init smb
    printf("\r\n\n\n\nEmbedded Control Electric Compass and Ranger\n"); //print beginning message

    Calibration();//Run calibration
	comp_cal();	//Compass calibration
    Choose_heading();	//Heading choice 
	printf("\r\nheading error");
	while(1) {	//inf loop, 40 ms it returns the heading	

		if (new_heading){	//enough overflows for a new heading COMPASS STUFF
			new_heading = 0;//Clear new_heading
			heading = ReadCompass();	//get compass heading	
			Steering_Servo();	//run steer func
		}//end if new heading
		
		if (new_range) { //if 80 ms has passed
			new_range=0;//Clear new_range
			range=ReadRanger();//read ranger
			start_ping();//start ping
			counts++;//set up text function
			Drive_Motor();	//run drive func
		}//end if new_range

		if (counts == 3){	//prevoudly output prined every 200 ms, now every 180 ms
			print_output();//Print data function. Delete this if faster output is desired
		}//end if counts
	}//end inf while
}//end main
int InputEventSensor::getData(std::queue<sensors_event_t> &eventQue) {
        struct input_event inputEvent[32];
        int count, ret;

        ret = read(pollfd, inputEvent, 32 * sizeof(struct input_event));
        if (ret < 0 || ret % sizeof(struct input_event)) {
                log_message(CRITICAL,"Read input event error! ret: %d", ret);
                return -1;
        }

        count = ret / sizeof(struct input_event);

        for (int i = 0; i < count; i++) {
                if ((inputEvent[i].type == EV_REL || inputEvent[i].type == EV_ABS) && !inputDataOverrun) {
					 log_message(CRITICAL,"in EV_REL\n");
 
                        float value = SensorHubHelper::ConvertToFloat(inputEvent[i].value, device.getType());
                      if ((inputEvent[i].type == EV_REL && inputEvent[i].code == REL_X) ||
                            (inputEvent[i].type == EV_ABS && inputEvent[i].code == ABS_X))
                                event.data[device.getMapper(AXIS_X)] = value * device.getScale(AXIS_X);
                        else if ((inputEvent[i].type == EV_REL && inputEvent[i].code == REL_Y) ||
                                 (inputEvent[i].type == EV_ABS && inputEvent[i].code == ABS_Y))
                                event.data[device.getMapper(AXIS_Y)] = value * device.getScale(AXIS_Y);
                        else if ((inputEvent[i].type == EV_REL && inputEvent[i].code == REL_Z) ||
                                 (inputEvent[i].type == EV_ABS && inputEvent[i].code == ABS_Z))
                                event.data[device.getMapper(AXIS_Z)] = value * device.getScale(AXIS_Z);

                }
                else if (inputEvent[i].type == EV_SYN) {
   					 log_message(CRITICAL,"in EV_SYN\n");
                     if (inputEvent[i].code == SYN_DROPPED) {
                                log_message(CRITICAL,"input event overrun");
                                inputDataOverrun = true;
                        }
                        else if (inputDataOverrun) {
                                inputDataOverrun = false;
                        }
                        else {
                                event.timestamp = timevalToNano(inputEvent[i].time);
                                if (Calibration != NULL)
                                        Calibration(&event, CALIBRATION_DATA, data.calibrationFile.c_str());
                                else if (device.getEventProperty() == VECTOR)
                                        event.acceleration.status = SENSOR_STATUS_ACCURACY_MEDIUM;
                                eventQue.push(event);
                        }
                }
        }

        return 0;
}
//*****************************************************************************
//
// Called by the NVIC as a result of GPIO port F interrupt event. For this
// application GPIO port F pin 0 corresponds to calibration button
//
//*****************************************************************************
void IntGPIOF(void) {
	unsigned long ulStatus;

	ulStatus = GPIOIntStatus(GPIO_PORTF_BASE, true);

	//
	// Clear all the pin interrupts that are set
	//
	GPIOIntClear(GPIO_PORTF_BASE, ulStatus);

	if (ulStatus & GPIO_PIN_4) {
		if (g_calibrationState == 0 || g_calibrationState == 1
				|| g_calibrationState == 3 || g_calibrationState == 5)
			Calibration();
	}
}
void _ExecCalibration(void) {
  int x,y;
  uint16_t data[6];
  uint16_t get_data[6];
  int ax_Phys[2],ay_Phys[2];
/* calculate log. Positions */
  int ax[2] = { 15, LCD_XSIZE -1-15};
//  const int ay[2] = { 15, LCD_YSIZE-1-15};
  int ay[2] = { LCD_YSIZE-1-15, 15};
  GUI_TOUCH_SetDefaultCalibration();
/* _Calibrate upper left */
  GUI_SetBkColor(GUI_RED);  
  GUI_Clear();
  GUI_SetColor(GUI_WHITE);  GUI_FillCircle(ax[0], ay[0], 10);
  GUI_SetColor(GUI_RED);    GUI_FillCircle(ax[0], ay[0], 5);
  GUI_SetColor(GUI_WHITE);
  GUI_DispStringAt("Press here", ax[0]+20, ay[0]);
  do {

#if 0
    GUI_PID_STATE State;
    GUI_TOUCH_GetState(&State);
	 if (State.Pressed) {
#endif

#if 1
  x = TPReadX();
  y = TPReadY();
  if ((x>=3700)&&(y>=3400)&&(x<3800)&&(y<3600)) {

#endif
      ax_Phys[0] = GUI_TOUCH_GetxPhys();
      ay_Phys[0] = GUI_TOUCH_GetyPhys();
      break;
    }
    GUI_Delay (3000);
  } while (1);
/* Tell user to release */
  GUI_Clear();
  GUI_DispStringAt("OK", ax[0]+20, ay[0]);
  do {
    GUI_PID_STATE State;
    GUI_TOUCH_GetState(&State);
    if (State.Pressed == 0) {
      break;
    }
    GUI_Delay (100);
  } while (1);
/* _Calibrate lower right */
  GUI_SetBkColor(GUI_RED);  
  GUI_Clear();
  GUI_SetColor(GUI_WHITE);  GUI_FillCircle(ax[1], ay[1], 10);
  GUI_SetColor(GUI_RED);    GUI_FillCircle(ax[1], ay[1], 5);
  GUI_SetColor(GUI_WHITE);
  GUI_SetTextAlign(GUI_TA_RIGHT);
  GUI_DispStringAt("Press here", ax[1]-20, ay[1]);
  do {

#if 1
  x = TPReadX();
  y = TPReadY();
  if ((y>450)&&(y<620)&&(x>350)&&(x<450)) {
#endif

#if 0
	GUI_PID_STATE State;
  	GUI_TOUCH_GetState(&State);
	if (State.Pressed) {
#endif

      ax_Phys[1] = GUI_TOUCH_GetxPhys();
      ay_Phys[1] = GUI_TOUCH_GetyPhys();
      break;
    }
    GUI_Delay (3000);
  } while (1);
  GUI_TOUCH_Calibrate(GUI_COORD_X, ax[0], ax[1], ax_Phys[0], ax_Phys[1]);
  GUI_TOUCH_Calibrate(GUI_COORD_Y, ay[0], ay[1], ay_Phys[0], ay_Phys[1]);
  { /* calculate and display values for configuration file */
    int x0, x1;
    int y0, y1;
    GUI_Clear();
    _Calibrate(GUI_COORD_X, ax[0], ax[1], ax_Phys[0], ax_Phys[1], &x0, &x1);
    _Calibrate(GUI_COORD_Y, ay[0], ay[1], ay_Phys[0], ay_Phys[1], &y0, &y1);
    GUI_DispStringAt("x0: ", 0, 0); GUI_DispDec(x0, 4); GUI_DispNextLine();
    GUI_DispString  ("x1: ");       GUI_DispDec(x1, 4); GUI_DispNextLine();
    GUI_DispString  ("y0: ");       GUI_DispDec(y0, 4); GUI_DispNextLine();
    GUI_DispString  ("y1: ");       GUI_DispDec(y1, 4); GUI_DispNextLine();
    GUI_DispString  ("Please touch display to continue...");
    GUI_Delay(1000);

	data[0]=  CAL_READY;
	data[1]= ax_Phys[0];
	data[2]= ay_Phys[0];
	data[3]= ax_Phys[1];
	data[4]= ay_Phys[1];

	#if 1
	save_calibrate_to_flash(data);
	get_calibrate_data(get_data);

	GUI_DispStringAt("x0: ", 100, 0); GUI_DispDec(get_data[1], 4); GUI_DispNextLine();
    GUI_DispString  ("x1: ");       GUI_DispDec(get_data[2], 4); GUI_DispNextLine();
    GUI_DispString  ("y0: ");       GUI_DispDec(get_data[3], 4); GUI_DispNextLine();
    GUI_DispString  ("y1: ");       GUI_DispDec(get_data[4], 4); GUI_DispNextLine();
	GUI_DispString  ("state: ");       GUI_DispDec(get_data[0], 4); GUI_DispNextLine();
	#endif

    do {
      GUI_PID_STATE State;
      GUI_TOUCH_GetState(&State);
      if (State.Pressed)
      break;
      GUI_Delay (10);
    } while (1);
  }
}



int run_cal(void)
{
  if(get_calibrate_state()== CAL_READY)
  {
  	get_calibration();
  }else{
	#if 1
  	 _ExecCalibration();
	#endif	

	#if 0
	Calibration();
	#endif
  }
}

int get_calibration(void)
{
  uint16_t cal_data[5];
  int ax_Phys[2],ay_Phys[2];
  int ax[2] = { 15, LCD_XSIZE -1-15};
  int ay[2] = { LCD_YSIZE-1-15, 15};

  get_calibrate_data(cal_data);

  ax_Phys[0] = cal_data[1];
  ay_Phys[0] = cal_data[2];
  
  ax_Phys[1] = cal_data[3];
  ay_Phys[1] = cal_data[4];
  
  GUI_TOUCH_Calibrate(GUI_COORD_X, ax[0], ax[1], ax_Phys[0], ax_Phys[1]);
  GUI_TOUCH_Calibrate(GUI_COORD_Y, ay[0], ay[1], ay_Phys[0], ay_Phys[1]);
}


#if 0			

void myAD2XY( int *adx , int *ady ){
 float f_dat;
 int dat1;

 f_dat = (float)(*ady - admy)/(float)(*adx - admx);
 if(f_dat>0){
  if( *adx>admx && admk[2] >=f_dat) dat1 = 1;
  else if( *adx>admx && admk[2] < f_dat ) dat1 =2;//2
  else if( *adx<admx && admk[0] >=f_dat ) dat1 =0;
  else if( *adx<admx && admk[0] < f_dat ) dat1 =3;//0
  else{ dat1 =0; }//*adx =0;*ady =0; }
 }else{
  if( *adx>admx && admk[1] >=f_dat) dat1 = 0;
  else if( *adx>admx && admk[1] < f_dat ) dat1 =1;//1
  else if( *adx<admx && admk[3] >=f_dat ) dat1 =3;
  else if( *adx<admx && admk[3] < f_dat ) dat1 =2;//3
  else{ dat1 =0; }//*adx =0;*ady =0; }
 }
 *adx = (int)(Factors[dat1][0].a*(*adx)+Factors[dat1][0].b*(*ady)+Factors[dat1][0].c); 
 *ady = (int)(Factors[dat1][1].a*(*adx)+Factors[dat1][1].b*(*ady)+Factors[dat1][1].c);
}
Beispiel #6
0
 /// Render and return calibration
 Calibration Tuning::renderCalibration(
   CalibrationMode _outputMode) const {
     return Calibration(*this,_outputMode);
 }
int main(void)
{	
	int16_t xSteps, ySteps;
	uint16_t x, y, xOld, yOld;
	uint8_t xNeutral8, yNeutral8;
	uint8_t xWheel = 0b11001100;
	uint8_t yWheel = 0b00110011;
	uint16_t xNeutral16, yNeutral16;
	uint8_t xFaktor = eeprom_read_byte(&cx);	
	uint8_t yFaktor = eeprom_read_byte(&cy);
	uint8_t xDeadzone = eeprom_read_byte(&dx);
	uint8_t yDeadzone = eeprom_read_byte(&dy);
	uint8_t useDeadzone;
	
	// Setup Ports
	DDRA = (1<<DDA6)|(1<<DDA7);
	DDRB = (1<<DDB0)|(1<<DDB1);
	PORTA = (1<<PORTA2)|(1<<PORTA3)|(1<<PORTA5);
	PORTB = (1<<PORTB2);
	
	// nicht benötigte Module deaktivieren
	PRR |= (1<<PRTIM0)|(1<<PRTIM1)|(1<<PRUSI);
	
	// 0.25 s warten bis Spannung stabil
	_delay_ms(250);		
	
	// bestimmen, ob Deadzones verwendet werden:
	if ( (xDeadzone==0) && (yDeadzone==0) )
		useDeadzone = 0;
	else
		useDeadzone = 1;
		
	// Setup ADC
	DIDR0 = (1<<ADC0D)|(1<<ADC1D);			// Digital input disable für PA0+1	
	ADMUX = 0x01;							// Kanal 1
	ADCSRA = (1<<ADPS0)|(1<<ADPS1);			// Taktteiler = 8 ==> f_ADC = 125 kHz
	ADCSRA |= (1<<ADEN);					// ADC aktivieren

		
	// 1. ADC Wandlung
	xNeutral16 = GetX();	
	
	// X Wert einlesen:
	xNeutral16 = GetX();	
	// falls Deadzone vorhanden, Absolutwert aus EEPROM lesen
	if (useDeadzone)		
		xNeutral16 = eeprom_read_word(&xAbsolute);				
	xNeutral8 = ScaleDown(xNeutral16, xFaktor);
	xOld = xNeutral8;
	
	// Y Wert einlesen:
	yNeutral16 = GetY();
	// falls Deadzone vorhanden, Absolutwert aus EEPROM lesen
	if (useDeadzone)		
		yNeutral16 = eeprom_read_word(&yAbsolute);							
	yNeutral8 = ScaleDown(yNeutral16, yFaktor);
	yOld = yNeutral8;	
	
	// Wenn PINB.2 = 0, dann beim nächsten Einschalten
	// normalen Calibration Mode aktivieren:
	if( ((1<<PINB2)&PINB)==0){
		eeprom_write_byte(&calibrationStep, 5);		
		eeprom_write_byte(&dx, 0);
		eeprom_write_byte(&dy, 0);		
		while(1);
	}
	
	// Wenn PINA.5 = 0, dann beim nächsten Einschalten
	// Calibration Mode mit Deadzone aktivieren:
	if( ((1<<PINA5)&PINA)==0){
		eeprom_write_byte(&calibrationStep, 1);
		while(1);
	}
	
	// Wenn calibration_step != 0, dann Calibration Mode ausführen
	if ( (eeprom_read_byte(&calibrationStep)) > 0x00 ){
		Calibration();
	}
	
	
    while(1)
    {	
		
		// X Wert einlesen:
		x = GetX();		
		// Deadzone berücksichtigen
		if (useDeadzone){			
			if (x > xNeutral16){
				if (x <= (xNeutral16+xDeadzone))
					x = xNeutral16;
				else
					x = x - xDeadzone;
			}
			if (x < xNeutral16){
				if (x >= (xNeutral16-xDeadzone))
					x = xNeutral16;
				else
					x = x + xDeadzone;
			}
		}	
		// runterskalieren	
		x = ScaleDown( x, xFaktor);
		// auf +/-84 begrenzen
		if (x>xNeutral8)
			if ( (x-xNeutral8) > MAX_RANGE)
				x = xNeutral8 + MAX_RANGE;
		if (x<xNeutral8)
			if ( (xNeutral8-x) > MAX_RANGE)
				x = xNeutral8 - MAX_RANGE;		
						
		// Y Wert einlesen:
		y = GetY();		
		// Deadzone berücksichtigen
		if (useDeadzone){			
			if (y > yNeutral16){
				if (y <= (yNeutral16+yDeadzone))
					y = yNeutral16;
				else
					y = y - yDeadzone;
			}
			if (y < yNeutral16){
				if (y >= (yNeutral16-yDeadzone))
					y = yNeutral16;
				else
					y = y + yDeadzone;
			}
		}		
		// runterskalieren	
		y = ScaleDown(y, yFaktor);		
		// auf +/-84 begrenzen
		if (y>yNeutral8)
			if ( (y-yNeutral8) > MAX_RANGE)
				y = yNeutral8 + MAX_RANGE;
		if (y<yNeutral8)
			if ( (yNeutral8-y) > MAX_RANGE)
				y = yNeutral8 - MAX_RANGE;
	
		//Anzahl Steps berechnen
		xSteps =  (int16_t) x - xOld;
		ySteps =  (int16_t) y - yOld;
		
		// wenn entspr. Jumper gebrückt, invertieren:
		if (INVX)
			xSteps = -xSteps;
		if (INVY)
			ySteps = -ySteps;
		
		//alte Werte für nächsten Durchlauf speichern
		xOld = x;
		yOld = y;
		
		//solange es noch Steps abzuarbeiten gibt:
		while ( (xSteps!=0) || (ySteps!=0) ){
								
			if (xSteps<0){
				xWheel = RotateLeft(xWheel);
				xSteps++;				
			}						
			if (xSteps>0){
				xWheel = RotateRight(xWheel);
				xSteps--;			
			}	
				
			if (ySteps>0){
				yWheel = RotateRight(yWheel);
				ySteps--;				
			}			
			if (ySteps<0){
				yWheel = RotateLeft(yWheel);
				ySteps++;			
			}		
			
			// neue XA/XB- und YA/YB-Werte ausgeben:			
			PORTB = (PORTB&0b11111100)|(xWheel & 0b00000011); 
			PORTA = (PORTA&0b00111111)|(yWheel & 0b11000000);
		}	
		
    }	
	
}
Beispiel #8
0
uint32_t CmdPwdAsserted(char *outputstr,T_MESSAGE *message)
{
  char *p;
  uint16_t bak_dr = 0;
  
  p=outputstr;  
  
  switch(message->m_type)
  {
  case CMD_DO:
    if( DoExecute((unsigned char)(message->m_intdata[0])) )  //执行成功
    {
#if LINGUA == EN  
      sprintf(outputstr,"DO Executed!Please Check the Di Change\r\n");
      p+=strlen("DO Executed!Please Check the Di Change\r\n");
#endif
      
#if LINGUA == CH  
      sprintf(outputstr,"遥控已操作,请查看遥信状态\r\n");
      p+=strlen("遥控已操作,请查看遥信状态\r\n");
#endif
    }
    else
    {     
      sprintf(outputstr,"总线状态异常,遥控执行失败!\r\n");
      p+=strlen("总线状态异常,遥控执行失败!\r\n");      
    }
    
    Shell_State=INIT;
    message->m_type=CMD_NULL;
    break;
    
  case CMD_SET:
  case CMD_COEF:
#if LINGUA == EN
    sprintf(outputstr,"Please Enter Item Resetting Parameter\r\n");     
    p+=strlen("Please Enter Item Resetting Parameter\r\n");
#endif 
#if LINGUA == CH
    sprintf(outputstr,"输入“通道序号 系数”\r\n");     
    p+=strlen("输入“通道序号 系数”\r\n");
#endif
    
    Shell_State=ENTER_DATA;
    break;
    
  case CMD_ADDR:
#if LINGUA == EN
    sprintf(outputstr,"Please Enter IP address\r\n");     
    p+=strlen("Please Enter IP address\r\n");
#endif
#if LINGUA == CH
    sprintf(outputstr,"输入IP地址\r\n");     
    p+=strlen("输入IP地址\r\n");
#endif
    
    Shell_State=ENTER_ADDR;
    break;  
    
  case CMD_CALB:
    Calibration();
    
#if LINGUA == EN  
    sprintf(outputstr,"Please Check the result of calibration\r\n");
    p+=strlen("Please Check the result of calibration\r\n");
#endif
#if LINGUA == CH  
    sprintf(outputstr,"校准完毕,核对遥测值\r\n");
    p+=strlen("校准完毕,核对遥测值\r\n");
#endif
    
    Shell_State=INIT;
    message->m_type=CMD_NULL;
    break;   
    
  case CMD_DCCAL:
    Can_Ticalib(CAN1);
    
#if LINGUA == EN  
    sprintf(outputstr,"Please Check the result of calibration\r\n");
    p+=strlen("Please Check the result of calibration\r\n");
#endif
#if LINGUA == CH  
    sprintf(outputstr,"标准源校准完毕,核对直流量\r\n");
    p+=strlen("标准源校准完毕,核对直流量\r\n");
#endif
    
    Shell_State=INIT;
    message->m_type=CMD_NULL;
    break;
    
  case CMD_PARA:
#if LINGUA == EN
    sprintf(outputstr,"Please Enter communiation settings\r\n");     
    p+=strlen("Please Enter communiation settings\r\n");
#endif
#if LINGUA == CH
    sprintf(outputstr,"输入通讯参数\r\n");     
    p+=strlen("输入通讯参数\r\n");
#endif
    
    Shell_State=ENTER_ADDR;
    break; 
    
    //TYH:添加恢復默认IP 
  case CMD_RESTOREIP:
    //infoNum = ShowInfo(outputstr, strRestoIP);   
    //p+=infoNum;
    sprintf(outputstr,"是否确认恢复默认IP, 确认请按<Y>, 按其它键返回\r\n");     
    p+=strlen("是否确认恢复默认IP, 确认请按<Y>, 按其它键返回\r\n");
    
    Shell_State=ENTER_RESTOREADDR;
    break;
    
    //TYH:20130508 恢复以太网 
  case CMD_RESET_ETH:
    //复位以太网
    Ethernet_HWRST();
    
    sprintf(outputstr,"是开始重置设备以太网,请等待.......\r\n");     
    p+=strlen("开始重置设备以太网,请等待.......\r\n");    
    
    Shell_State=INIT;
    message->m_type=CMD_NULL;
    break;
    
    //TYH:20130508 设置固件升级 
  case CMD_UPDATE_FIRMWARE:  
    //写备份寄存器 'KP_DR10', 用于启动升级固件
    bak_dr = BKP_ReadBackupRegister(BKP_DR10);
    if(bak_dr != 0x0707)
      BKP_WriteBackupRegister(BKP_DR10, 0x0707);    
    
    sprintf(outputstr,"bak_dr=0x%4x 设置固件升级, 请重启设备启动升级!\r\n", bak_dr);     
    p+=strlen("bak_dr=0xffff 设置固件升级, 请重启设备启动升级!\r\n");  
    
    Shell_State=INIT;
    message->m_type=CMD_NULL;    
    break;
    
    //TYH:20130530 设置以太网状态判断时间  
  case CMD_ETH_LINK_TIME:
  case CMD_ETH_RECV_TIME:
    sprintf(outputstr,"输入以太网判断时间参数\r\n");     
    p+=strlen("输入以太网判断时间参数\r\n");
    
    Shell_State=SET_ETH_TIME;
    break;    
    
  default:
    break;  
    
  }
  return (p-outputstr);	  
}
Beispiel #9
0
EllipsoidFitter::Calibration EllipsoidFitter::calculateFit(void) const
	{
	/*********************************************************************
	First step: Fit a quadric to the point set by least-squares
	minimization based on algebraic distance.
	*********************************************************************/
	
	/* Create the least-squares system: */
	Math::Matrix a(10,10,0.0);
	
	/* Process all points: */
	for(Misc::ChunkedArray<Point>::const_iterator pIt=points.begin();pIt!=points.end();++pIt)
		{
		/* Create the point's associated linear equation: */
		double eq[10];
		eq[0]=(*pIt)[0]*(*pIt)[0];
		eq[1]=2.0*(*pIt)[0]*(*pIt)[1];
		eq[2]=2.0*(*pIt)[0]*(*pIt)[2];
		eq[3]=2.0*(*pIt)[0];
		eq[4]=(*pIt)[1]*(*pIt)[1];
		eq[5]=2.0*(*pIt)[1]*(*pIt)[2];
		eq[6]=2.0*(*pIt)[1];
		eq[7]=(*pIt)[2]*(*pIt)[2];
		eq[8]=2.0*(*pIt)[2];
		eq[9]=1.0;
		
		/* Insert the equation into the least-squares system: */
		for(unsigned int i=0;i<10;++i)
			for(unsigned int j=0;j<10;++j)
				a(i,j)+=eq[i]*eq[j];
		}
	
	/* Find the least-squares system's smallest eigenvalue: */
	std::pair<Math::Matrix,Math::Matrix> qe=a.jacobiIteration();
	unsigned int minEIndex=0;
	double minE=Math::abs(qe.second(0,0));
	for(unsigned int i=1;i<10;++i)
		{
		if(minE>Math::abs(qe.second(i,0)))
			{
			minEIndex=i;
			minE=Math::abs(qe.second(i,0));
			}
		}
	
	/* Create the quadric's defining matrices: */
	Math::Matrix qa(3,3);
	qa(0,0)=qe.first(0,minEIndex);
	qa(0,1)=qe.first(1,minEIndex);
	qa(0,2)=qe.first(2,minEIndex);
	qa(1,0)=qe.first(1,minEIndex);
	qa(1,1)=qe.first(4,minEIndex);
	qa(1,2)=qe.first(5,minEIndex);
	qa(2,0)=qe.first(2,minEIndex);
	qa(2,1)=qe.first(5,minEIndex);
	qa(2,2)=qe.first(7,minEIndex);
	Math::Matrix qb(3,1);
	qb(0)=qe.first(3,minEIndex);
	qb(1)=qe.first(6,minEIndex);
	qb(2)=qe.first(8,minEIndex);
	double qc=qe.first(9,minEIndex);
	
	/* Calculate the quadric's principal axes: */
	qe=qa.jacobiIteration();
	std::cout<<std::fixed<<std::setprecision(6);
	std::cout<<std::setw(9)<<qe.first<<std::endl;
	std::cout<<std::setw(9)<<qe.second<<std::endl<<std::endl;
	std::cout.unsetf(std::ios_base::floatfield);
	
	/* "Complete the square" to calculate the quadric's centroid and radii: */
	Math::Matrix qbp=qb.divideFullPivot(qe.first);
	Math::Matrix cp(3,1);
	for(int i=0;i<3;++i)
		cp(i)=-qbp(i)/qe.second(i);
	Math::Matrix c=qe.first*cp;
	std::cout<<"Centroid: "<<c(0)<<", "<<c(1)<<", "<<c(2)<<std::endl;
	double rhs=-qc;
	for(int i=0;i<3;++i)
		rhs+=Math::sqr(qbp(i))/qe.second(i);
	double radii[3];
	for(int i=0;i<3;++i)
		radii[i]=Math::sqrt(rhs/qe.second(i));
	std::cout<<"Radii: "<<radii[0]<<", "<<radii[1]<<", "<<radii[2]<<std::endl;
	Scalar averageRadius=Math::pow(radii[0]*radii[1]*radii[2],1.0/3.0);
	std::cout<<"Average radius: "<<averageRadius<<std::endl;
		
	/* Calculate the calibration matrix: */
	Math::Matrix ellP(4,4,1.0);
	for(int i=0;i<3;++i)
		for(int j=0;j<3;++j)
			ellP(i,j)=qe.first(i,j);
	Math::Matrix ellScale(4,4,1.0);
	for(int i=0;i<3;++i)
		ellScale(i,i)=averageRadius/radii[i];
	Math::Matrix ell=ellP;
	ell.makePrivate();
	for(int i=0;i<3;++i)
		ell(i,3)=c(i);
	Math::Matrix ellInv=ell.inverseFullPivot();
	Math::Matrix calib=ellP*ellScale*ellInv;
	std::cout<<std::fixed<<std::setprecision(6);
	std::cout<<std::setw(9)<<calib<<std::endl;
	std::cout.unsetf(std::ios_base::floatfield);
	
	/* Calculate the calibration residual: */
	double rms=0.0;
	for(Misc::ChunkedArray<Point>::const_iterator pIt=points.begin();pIt!=points.end();++pIt)
		{
		/* Calibrate the point: */
		Math::Matrix p(4,1);
		for(int i=0;i<3;++i)
			p(i)=(*pIt)[i];
		p(3)=1.0;
		Math::Matrix cp=calib*p;
		rms+=Math::sqr(Math::sqrt(Math::sqr(cp(0))+Math::sqr(cp(1))+Math::sqr(cp(2)))-averageRadius);
		}
	std::cout<<"Calibration residual: "<<Math::sqrt(rms/double(points.size()))<<std::endl;
	
	/* Create and return the calibration result: */
	Matrix result;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			result(i,j)=calib(i,j);
	return Calibration(result,averageRadius);
	}
Beispiel #10
0
 /// Render and return calibration
 Calibration Tuning::renderCalibration() const {
     return Calibration(*this);
 }
//*****************************************************************************
//
// Main application entry point.
//
//*****************************************************************************
int main(void) {
	int_fast32_t i32IPart[17], i32FPart[17];
	uint_fast32_t ui32Idx, ui32CompDCMStarted;
	float pfData[17];
	float *pfAccel, *pfGyro, *pfMag, *pfEulers, *pfQuaternion;
	float *direction;

	//
	// Initialize convenience pointers that clean up and clarify the code
	// meaning. We want all the data in a single contiguous array so that
	// we can make our pretty printing easier later.
	//
	pfAccel = pfData;
	pfGyro = pfData + 3;
	pfMag = pfData + 6;
	pfEulers = pfData + 9;
	pfQuaternion = pfData + 12;
	direction = pfData + 16;

	//
	// Setup the system clock to run at 40 Mhz from PLL with crystal reference
	//
	ROM_SysCtlClockSet(
			SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ
					| SYSCTL_OSC_MAIN);

	//
	// Enable port E used for motion interrupt.
	//
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

	//
	// Enable port F used for calibration.
	//
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

	//
	// Initialize the UART.
	//
	ConfigureUART();

	/* EEPROM SETTINGS */
	SysCtlPeripheralEnable(SYSCTL_PERIPH_EEPROM0); // EEPROM activate
	EEPROMInit(); // EEPROM start

	//
	// Print the welcome message to the terminal.
	//
	UARTprintf("\033[2JMPU9150 Raw Example\n");

	//
	// Set the color to a purple approximation.
	//
	g_pui32Colors[RED] = 0x8000;
	g_pui32Colors[BLUE] = 0x8000;
	g_pui32Colors[GREEN] = 0x8000;

	//
	// Initialize RGB driver.
	//
	RGBInit(0);
	RGBColorSet(g_pui32Colors);
	RGBIntensitySet(0.5f);
	RGBEnable();

	// Initialize BGLib
	bglib_output = output;
	ConfigureBLE();

	//
	// The I2C3 peripheral must be enabled before use.
	//
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

	//
	// Configure the pin muxing for I2C3 functions on port D0 and D1.
	//
	ROM_GPIOPinConfigure(GPIO_PD0_I2C3SCL);
	ROM_GPIOPinConfigure(GPIO_PD1_I2C3SDA);

	//
	// Select the I2C function for these pins.  This function will also
	// configure the GPIO pins pins for I2C operation, setting them to
	// open-drain operation with weak pull-ups.  Consult the data sheet
	// to see which functions are allocated per pin.
	//
	GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);
	ROM_GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1);

	//
	// Configure and Enable the GPIO interrupt. Used for INT signal from the
	// MPU9150
	//
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_2);
	GPIOIntEnable(GPIO_PORTE_BASE, GPIO_PIN_2);
	ROM_GPIOIntTypeSet(GPIO_PORTE_BASE, GPIO_PIN_2, GPIO_FALLING_EDGE);
	ROM_IntEnable(INT_GPIOE);

	//
	// Keep only some parts of the systems running while in sleep mode.
	// GPIOE is for the MPU9150 interrupt pin.
	// UART0 is the virtual serial port
	// TIMER0, TIMER1 and WTIMER5 are used by the RGB driver
	// I2C3 is the I2C interface to the ISL29023
	//
	ROM_SysCtlPeripheralClockGating(true);
	ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOE);
	ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
	ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER0);
	ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER1);
	ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_I2C3);
	ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_WTIMER5);

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

	//
	// Initialize I2C3 peripheral.
	//
	I2CMInit(&g_sI2CInst, I2C3_BASE, INT_I2C3, 0xff, 0xff,
			ROM_SysCtlClockGet());

	//
	// Initialize the MPU9150 Driver.
	//
	MPU9150Init(&g_sMPU9150Inst, &g_sI2CInst, MPU9150_I2C_ADDRESS,
			MPU9150AppCallback, &g_sMPU9150Inst);

	//
	// Wait for transaction to complete
	//
	MPU9150AppI2CWait(__FILE__, __LINE__);

	//
	// Configure the sampling rate to 1000 Hz / (1+24).
	//
	g_sMPU9150Inst.pui8Data[0] = 24;
	MPU9150Write(&g_sMPU9150Inst, MPU9150_O_SMPLRT_DIV, g_sMPU9150Inst.pui8Data,
			1, MPU9150AppCallback, &g_sMPU9150Inst);

	//
	// Wait for transaction to complete
	//
	MPU9150AppI2CWait(__FILE__, __LINE__);

	//
	// Write application specifice sensor configuration such as filter settings
	// and sensor range settings.
	//
	g_sMPU9150Inst.pui8Data[0] = MPU9150_CONFIG_DLPF_CFG_94_98;
	g_sMPU9150Inst.pui8Data[1] = MPU9150_GYRO_CONFIG_FS_SEL_250;
	g_sMPU9150Inst.pui8Data[2] = (MPU9150_ACCEL_CONFIG_ACCEL_HPF_5HZ
			| MPU9150_ACCEL_CONFIG_AFS_SEL_2G);
//	g_sMPU9150Inst.pui8Data[2] = MPU9150_ACCEL_CONFIG_AFS_SEL_2G;
	MPU9150Write(&g_sMPU9150Inst, MPU9150_O_CONFIG, g_sMPU9150Inst.pui8Data, 3,
			MPU9150AppCallback, &g_sMPU9150Inst);

	//
	// Wait for transaction to complete
	//
	MPU9150AppI2CWait(__FILE__, __LINE__);

	//
	// Configure the data ready interrupt pin output of the MPU9150.
	//
	g_sMPU9150Inst.pui8Data[0] = MPU9150_INT_PIN_CFG_INT_LEVEL
			| MPU9150_INT_PIN_CFG_INT_RD_CLEAR
			| MPU9150_INT_PIN_CFG_LATCH_INT_EN;
	g_sMPU9150Inst.pui8Data[1] = MPU9150_INT_ENABLE_DATA_RDY_EN;
	MPU9150Write(&g_sMPU9150Inst, MPU9150_O_INT_PIN_CFG,
			g_sMPU9150Inst.pui8Data, 2, MPU9150AppCallback, &g_sMPU9150Inst);

	//
	// Wait for transaction to complete
	//
	MPU9150AppI2CWait(__FILE__, __LINE__);

	//
	// Initialize the DCM system. 40 hz sample rate.
	// accel weight = .2, gyro weight = .8, mag weight = .2
	//
	CompDCMInit(&g_sCompDCMInst, 1.0f / 40.0f, 0.2f, 0.6f, 0.2f);

	//
	// Enable blinking indicates config finished successfully
	//
	RGBBlinkRateSet(1.0f);

	//
	// Configure and Enable the GPIO interrupt. Used for calibration
	//
	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
	HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
	GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA,
			GPIO_PIN_TYPE_STD_WPU);
	ROM_IntEnable(INT_GPIOF);
	ROM_GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
	GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_4);
	g_calibrationState = 0;

	ui32CompDCMStarted = 0;
	// Configure the white noise, read the error from EEPROM
	EEPROMRead((uint32_t *) zeroErrorAccel,
			EEPROM_ZERO_ERROR_ACCELERATION_ADDRESS, 12);
	EEPROMRead((uint32_t *) linearErrorAccel,
			EEPROM_LINEAR_ERROR_ACCELERATION_ADDRESS, 12);
	EEPROMRead((uint32_t *) zeroErrorGyro, EEPROM_ZERO_ERROR_GYROSCOPE_ADDRESS,
			12);

	while (1) {
		//
		// Go to sleep mode while waiting for data ready.
		//
		while (!g_vui8I2CDoneFlag) {
			//ROM_SysCtlSleep();
		}

		//
		// Clear the flag
		//
		g_vui8I2CDoneFlag = 0;

		//
		// Get floating point version of the Accel Data in m/s^2.
		//
		MPU9150DataAccelGetFloat(&g_sMPU9150Inst, pfAccel, pfAccel + 1,
				pfAccel + 2);

		//
		// Get floating point version of angular velocities in rad/sec
		//
		MPU9150DataGyroGetFloat(&g_sMPU9150Inst, pfGyro, pfGyro + 1,
				pfGyro + 2);

		//
		// Get floating point version of magnetic fields strength in tesla
		//
		MPU9150DataMagnetoGetFloat(&g_sMPU9150Inst, pfMag, pfMag + 1,
				pfMag + 2);

		if (g_calibrationState == 2) {
			zeroErrorAccel[0] = (pfAccel[0]
					+ zeroErrorAccel[0] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			zeroErrorAccel[1] = (pfAccel[1]
					+ zeroErrorAccel[1] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			accelAtGravity[2] = (pfAccel[2]
					+ accelAtGravity[2] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			zeroErrorGyro[0] = (pfGyro[0]
					+ zeroErrorGyro[0] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			zeroErrorGyro[1] = (pfGyro[1]
					+ zeroErrorGyro[1] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			zeroErrorGyro[2] = (pfGyro[2]
					+ zeroErrorGyro[2] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			g_calibrationCount++;
			if (g_calibrationCount > 500) {
				Calibration();
			}
			continue;
		} else if (g_calibrationState == 4) {
			zeroErrorAccel[2] = (pfAccel[2]
					+ zeroErrorAccel[2] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			accelAtGravity[1] = (pfAccel[1]
					+ accelAtGravity[1] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			g_calibrationCount++;
			if (g_calibrationCount > 500) {
				Calibration();
			}
			continue;
		} else if (g_calibrationState == 6) {
			accelAtGravity[0] = (pfAccel[0]
					+ accelAtGravity[0] * g_calibrationCount)
					/ (g_calibrationCount + 1);
			g_calibrationCount++;
			if (g_calibrationCount > 500) {
				Calibration();
			}
			continue;
		}

		// Cancel out white noise
//		pfAccel[0] = pfAccel[0] - zeroErrorAccel[0];
//		pfAccel[1] = pfAccel[1] - zeroErrorAccel[1];
//		pfAccel[2] = pfAccel[2] - zeroErrorAccel[2];
//		pfGyro[0] = pfGyro[0] - zeroErrorGyro[0];
//		pfGyro[1] = pfGyro[1] - zeroErrorGyro[1];
//		pfGyro[2] = pfGyro[2] - zeroErrorGyro[2];
//		// Straighten out linear noise
//		pfAccel[0] = pfAccel[0] * (1 + linearErrorAccel[0]);
//		pfAccel[1] = pfAccel[1] * (1 + linearErrorAccel[1]);
//		pfAccel[2] = pfAccel[2] * (1 + linearErrorAccel[2]);

		//
		// Check if this is our first data ever.
		//
		if (ui32CompDCMStarted == 0) {
			//
			// Set flag indicating that DCM is started.
			// Perform the seeding of the DCM with the first data set.
			//
			ui32CompDCMStarted = 1;
			CompDCMMagnetoUpdate(&g_sCompDCMInst, pfMag[0], pfMag[1], pfMag[2]);
			CompDCMAccelUpdate(&g_sCompDCMInst, pfAccel[0], pfAccel[1],
					pfAccel[2]);
			CompDCMGyroUpdate(&g_sCompDCMInst, pfGyro[0], pfGyro[1], pfGyro[2]);
			CompDCMStart(&g_sCompDCMInst);
		} else {
			//
			// DCM Is already started.  Perform the incremental update.
			//
			CompDCMMagnetoUpdate(&g_sCompDCMInst, pfMag[0], pfMag[1], pfMag[2]);
			CompDCMAccelUpdate(&g_sCompDCMInst, pfAccel[0], pfAccel[1],
					pfAccel[2]);
			CompDCMGyroUpdate(&g_sCompDCMInst, -pfGyro[0], -pfGyro[1],
					-pfGyro[2]);
			CompDCMUpdate(&g_sCompDCMInst);
		}

		//
		// Increment the skip counter.  Skip counter is used so we do not
		// overflow the UART with data.
		//
		g_ui32PrintSkipCounter++;
		if (g_ui32PrintSkipCounter >= PRINT_SKIP_COUNT) {
			//
			// Reset skip counter.
			//
			g_ui32PrintSkipCounter = 0;

			//
			// Get Euler data. (Roll Pitch Yaw)
			//
			CompDCMComputeEulers(&g_sCompDCMInst, pfEulers, pfEulers + 1,
					pfEulers + 2);

			//
			// Get Quaternions.
			//
			CompDCMComputeQuaternion(&g_sCompDCMInst, pfQuaternion);

			//
			// convert mag data to micro-tesla for better human interpretation.
			//
			pfMag[0] *= 1e6;
			pfMag[1] *= 1e6;
			pfMag[2] *= 1e6;

			//
			// Convert Eulers to degrees. 180/PI = 57.29...
			// Convert Yaw to 0 to 360 to approximate compass headings.
			//
			pfEulers[0] *= 57.295779513082320876798154814105f;
			pfEulers[1] *= 57.295779513082320876798154814105f;
			pfEulers[2] *= 57.295779513082320876798154814105f;
			if (pfEulers[2] < 0) {
				pfEulers[2] += 360.0f;
			}

			// Use pfMag to display degrees of the Magnetomer's x-axis
			// (y-axis of accelerometer and gyroscope) to the east of
			// magnetic north pole
//			direction[0] = 0;
//			if (pfMag[1] == 0) {
//				if (pfMag[0] > 0) {
//					direction[0] = 0;
//				} else {
//					direction[0] = 180;
//				}
//			} else if (pfMag[1] > 0) {
//				direction[0] = 90 - atan2f(pfMag[0], pfMag[1]) * 180 / 3.14159265359;
//			} else if (pfMag[1] < 0) {
//				direction[0] = 270 - atan2f(pfMag[0], pfMag[1]) * 180 / 3.14159265359;
//			}

			//
			// Now drop back to using the data as a single array for the
			// purpose of decomposing the float into a integer part and a
			// fraction (decimal) part.
			//
			for (ui32Idx = 0; ui32Idx < 17; ui32Idx++) {
				//
				// Conver float value to a integer truncating the decimal part.
				//
				i32IPart[ui32Idx] = (int32_t) pfData[ui32Idx];

				//
				// Multiply by 1000 to preserve first three decimal values.
				// Truncates at the 3rd decimal place.
				//
				i32FPart[ui32Idx] = (int32_t) (pfData[ui32Idx] * 1000.0f);

				//
				// Subtract off the integer part from this newly formed decimal
				// part.
				//
				i32FPart[ui32Idx] = i32FPart[ui32Idx]
						- (i32IPart[ui32Idx] * 1000);

				//
				// make the decimal part a positive number for display.
				//
				if (i32FPart[ui32Idx] < 0) {
					i32FPart[ui32Idx] *= -1;
				}
			}

			if (g_bleUserFlag == 1) {
				g_bleFlag = 0;
				ble_cmd_attributes_write(58, 0, 12, (uint8_t*)pfEuler);
				while (g_bleFlag == 0) {
				}
			} else if (g_bleDisconnectFlag == 1) {
				ConfigureBLE();
			}

			//
			// Print the acceleration numbers in the table.
			//
//			UARTprintf("%3d.%03d, ", i32IPart[0], i32FPart[0]);
//			UARTprintf("%3d.%03d, ", i32IPart[1], i32FPart[1]);
//			UARTprintf("%3d.%03d\n", i32IPart[2], i32FPart[2]);
//
//			//
//			// Print the angular velocities in the table.
//			//
//			UARTprintf("%3d.%03d, ", i32IPart[3], i32FPart[3]);
//			UARTprintf("%3d.%03d, ", i32IPart[4], i32FPart[4]);
//			UARTprintf("%3d.%03d\n", i32IPart[5], i32FPart[5]);
//
//			//
//			// Print the magnetic data in the table.
//			//
//			UARTprintf("%3d.%03d, ", i32IPart[6], i32FPart[6]);
//			UARTprintf("%3d.%03d, ", i32IPart[7], i32FPart[7]);
//			UARTprintf("%3d.%03d\n", i32IPart[8], i32FPart[8]);
//
//			//
//			// Print the direction in the table.
//			//
//			UARTprintf("%3d.%03d\n", i32IPart[16], i32FPart[16]);
//			//
//			// Print the Eulers in a table.
//			//
//			UARTprintf("%3d.%03d, ", i32IPart[9], i32FPart[9]);
//			UARTprintf("%3d.%03d, ", i32IPart[10], i32FPart[10]);
//			UARTprintf("%3d.%03d\n", i32IPart[11], i32FPart[11]);
//
//			//
//			// Print the quaternions in a table format.
//			//
//			UARTprintf("\033[19;14H%3d.%03d", i32IPart[12], i32FPart[12]);
//			UARTprintf("\033[19;32H%3d.%03d", i32IPart[13], i32FPart[13]);
//			UARTprintf("\033[19;50H%3d.%03d", i32IPart[14], i32FPart[14]);
//			UARTprintf("\033[19;68H%3d.%03d", i32IPart[15], i32FPart[15]);

		}
	}
}
bool Communication::DataListening()
{
		u8 ch=0;
		u8 data[30]={0};
		u8 check=0;
		u8 num = usart.ReceiveBufferSize();
		if(num>0)
		{
				usart.GetReceivedData(&ch,1);
				if(ch == 0xaa)
				{
					usart.GetReceivedData(&ch,1);
					if(ch == 0xaf)
					{
						//功能字判断
						data[0] = 0xaa;
						data[1] = 0xaf;
						usart.GetReceivedData(&ch,1);
						if(ch == 0x01)//命令集1
						{
							data[2]= 0x01;
							while(usart.ReceiveBufferSize()<2);//等待数据
							usart.GetReceivedData(data+3,3);							
							check=data[5];							
							if( Calibration(data,data[3]+4,check )) //如果校验正确
							{
								if(data[4] == 0x01) //ACC校准
								{
										mAcc_Calibrate = true;
										return true;
								}
								else if(data[4] == 0x02)//GYRO校准
								{
										mGyro_Calibrate = true;
										return true;
								}
								else if(data[4] == 0x04)//MAG校准
								{
									  mMag_Calibrate = true;
									  return true;
								}
								else if(data[4] == 0xa0)//飞机锁定
								{
									mClockState = true;
									reply(data[2],check);
									return true;
								}
								else if(data[4] == 0xa1)//飞机解锁
								{
									mClockState = false;
									reply(data[2],check);
									return true;
								}
								else
								{
									//未知命令
									return false;
								}
							}
							else
								return false; //校准错误
						}
						else if(ch == 0x02)//命令集2
						{
							data[2]= ch;
							while(usart.ReceiveBufferSize()<3);//等待数据
							usart.GetReceivedData(data+3,3);
							check=data[5];
							if( Calibration(data,data[3]+4,check )) //如果校验正确
							{
								if(data[4] == 0x01) //PID请求
								{
										mGetPid=true;
										return true;
								}
								else if(data[4]==0XA0)//读取下位机版本信息
								{
								   return true;
								}
								else 
								{
									//未知命令
									return false;
								}
								
							}
							else //校验错误
								return false;
						
						}
						else if(ch == 0x03)//控制信息
						{
							data[2]= ch;
							while(usart.ReceiveBufferSize()<22);//等待数据
							usart.GetReceivedData(data+3,22);							
							check=data[24];							
							if( Calibration(data,data[3]+4,check )) //如果校验正确
							{								
								mRcvTargetThr =(u16)data[4]*256+ data[5];
								mRcvTargetYaw =(u16)data[6]*256+ data[7];
								mRcvTargetRoll =(u16)data[8]*256+ data[9];
								mRcvTargetPitch =(u16)data[10]*256+ data[11];
								return true;
							}
							return false;
						}
						else if(ch ==0x10 ||ch ==0x11 ||ch ==0x12) //PID更新
						{
							static u8 PIDnumber;
							PIDnumber = ch -0x10;
							if(PIDnumber>2) //防止PID数值越界
							{
								return false;
							}
							data[2]= ch;
							while(usart.ReceiveBufferSize()<20);//等待数据
							usart.GetReceivedData(data+3,20);
							check=data[22];
							if( Calibration(data,data[3]+4,check )) //如果校验正确
							{
					
									PID[PIDnumber][0]=((u16)data[4]*256+data[5])/1000.0;
									PID[PIDnumber][1]=((u16)data[6]*256+data[7])/1000.0;
									PID[PIDnumber][2]=((u16)data[8]*256+data[9])/1000.0;
								
									PID[PIDnumber][3]=((u16)data[10]*256+data[11])/1000.0;
									PID[PIDnumber][4]=((u16)data[12]*256+data[13])/1000.0;
									PID[PIDnumber][5]=((u16)data[14]*256+data[15])/1000.0;
								
									PID[PIDnumber][6]=((u16)data[16]*256+data[17])/1000.0;
									PID[PIDnumber][7]=((u16)data[18]*256+data[19])/1000.0;
									PID[PIDnumber][8]=((u16)data[20]*256+data[21])/1000.0;
									reply(ch,check);
									mPidUpdata = true;
									return true;
							}
							else
								return false;
						
						}
						else
						{
								//未知功能字
							return false;
						}
						
					}
					else
						return false; //不是帧头
				}
				else
					return false;		//不是帧头		
		}
		else
			return false;//没接收到数据
		
}