int DMP::getAttitude() { if (!dmpReady) return -1; // wait for FIFO count > 42 bits do { fifoCount = mpu.getFIFOCount(); }while (fifoCount<42); if (fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); printf("FIFO overflow!\n"); return -1; // otherwise, check for DMP data ready interrupt //(this should happen frequently) } else { //read packet from fifo mpu.getFIFOBytes(fifoBuffer, packetSize); mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); for (int i=0;i<DIM;i++){ //offset removal ypr[i]-=m_ypr_off[i]; //scaling for output in degrees ypr[i]*=180/M_PI; } //printf(" %7.2f %7.2f %7.2f\n",ypr[0],ypr[1],ypr[2]); //unwrap yaw when it reaches 180 ypr[0] = wrap_180(ypr[0]); //change sign of ROLL, MPU is attached upside down ypr[2]*=-1.0; mpu.dmpGetGyro(g, fifoBuffer); //0=gyroX, 1=gyroY, 2=gyroZ //swapped to match Yaw,Pitch,Roll //Scaled from deg/s to get tr/s for (int i=0;i<DIM;i++){ gyro[i] = (float)(g[DIM-i-1])/131.0/360.0; } // printf("gyro %7.2f %7.2f %7.2f \n", (float)g[0]/131.0, // (float)g[1]/131.0, // (float)g[2]/131.0); return 0; } }
void Gyro_update(void) { /* reset FIFO buffer and wait for first data */ mpu.resetFIFO(); mpu_interrupt = false; do { while (!mpu_interrupt) { ; } mpu_interrupt = false; mpuIntStatus = mpu.getIntStatus(); fifoCount = mpu.getFIFOCount(); } while (!(mpuIntStatus & 0x02)); /* reading data */ mpu.getFIFOBytes(fifoBuffer, packetSize); mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); /* converting to degrees and using offsets */ for (uint8_t i = 0; i < 3; i++) { ypr[i] = (ypr[i] * 180 / M_PI) + ypr_offsets[i]; } }
void DMP::initialize(){ //This routine waits for the yaw angle to stop //drifting if (!dmpReady) return; printf("Initializing IMU...\n"); for (int n=1;n<3500;n++) { // wait for FIFO count > 42 bits do { fifoCount = mpu.getFIFOCount(); }while (fifoCount<42); if (fifoCount >= 1024) { // reset so we can continue cleanly mpu.resetFIFO(); printf("FIFO overflow!\n"); // otherwise, check for DMP data ready interrupt //(this should happen frequently) } else { //read packet from fifo mpu.getFIFOBytes(fifoBuffer, packetSize); mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); // printf("yaw = %f, pitch = %f, roll = %f\n", // ypr[YAW]*180/M_PI, ypr[PITCH]*180/M_PI, // ypr[ROLL]*180/M_PI); } } printf("IMU init done; offset values are :\n"); printf("yaw = %f, pitch = %f, roll = %f\n\n", ypr[YAW]*180/M_PI, ypr[PITCH]*180/M_PI, ypr[ROLL]*180/M_PI); initialized = true; }
void gyro_acc() { // if programming failed, don't try to do anything if (!dmpReady) return; // get current FIFO count fifoCount = mpu.getFIFOCount(); if (fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); printf("FIFO overflow!\n"); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (fifoCount >= 42) { // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); printf("ypr %7.2f %7.2f %7.2f t:%d ", ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI,count_time); count_time++; #endif #ifdef OUTPUT_READABLE_WORLDACCEL // display initial world-frame acceleration, adjusted to remove gravity // and rotated based on known orientation from quaternion mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); printf("aworld %6d %6d %6d ", aaWorld.x, aaWorld.y, aaWorld.z); #endif }
void loop() { while(1){ mpuInterrupt = false; // char buf[10]={0}; // // UART_TX((uint8_t *)buf, sprintf(buf,"%u\r\n", HAL_GetTick())); // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { // cnt++; // time_now = HAL_GetTick(); // if((time_now-time_old) >= 1000){ // time_old = time_now; // char buffer[10]={0}; // UART_TX((uint8_t *)buffer, sprintf(buffer,"%u\r\n", (int)cnt )); // UART_TX((uint8_t*)"\r\n", sizeof("\r\n")); // cnt=0; // } // UART_TX((uint8_t*)"x=", sizeof("x=")); // UART_Float_TX( (ypr[2] * 180/M_PI) ); // // UART_TX((uint8_t*)"y=", sizeof("y=")); // UART_Float_TX( (ypr[1] * 180/M_PI) ); // // UART_TX((uint8_t*)"z=", sizeof("z=")); // UART_Float_TX( (ypr[0] * 180/M_PI) ); // UART_TX((uint8_t*)"\n\r", sizeof("\n\r")); // BSP_LED_Toggle(LED4); // UART_TX((uint8_t*)"MAIN\r\n", sizeof("MAIN\r\n")); // other program behavior stuff here // . // . // . // if you are really paranoid you can frequently test in between other // stuff to see if mpuInterrupt is true, and if so, "break;" from the // while() loop to immediately process the MPU data // . // . // . } // reset interrupt flag and get INT_STATUS byte mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus == 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); UART_TX((uint8_t*)"FIFO Overflow\r\n", sizeof("FIFO Overflow\r\n")); BSP_LED_Toggle(LED5); } // otherwise, check for DMP data ready interrupt (this should happen frequently) else if(mpuIntStatus == 0x01) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; #ifdef OUTPUT_READABLE_QUATERNION // display quaternion values in easy matrix form: w x y z mpu.dmpGetQuaternion(&q, fifoBuffer); Serial.print("quat\t"); Serial.print(q.w); Serial.print("\t"); Serial.print(q.x); Serial.print("\t"); Serial.print(q.y); Serial.print("\t"); Serial.println(q.z); #endif #ifdef OUTPUT_READABLE_EULER // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetEuler(euler, &q); Serial.print("euler\t"); Serial.print(euler[0] * 180/M_PI); Serial.print("\t"); Serial.print(euler[1] * 180/M_PI); Serial.print("\t"); Serial.println(euler[2] * 180/M_PI); #endif #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); // trace_printf("ypr\t"); // trace_printf("%f", ypr[0] * 180/M_PI); // trace_printf("\t"); // trace_printf("%d", ypr[1] * 180/M_PI); // trace_printf("\t"); // trace_printf("%d\n", ypr[2] * 180/M_PI); #endif #ifdef OUTPUT_READABLE_REALACCEL // display real acceleration, adjusted to remove gravity mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); Serial.print("areal\t"); Serial.print(aaReal.x); Serial.print("\t"); Serial.print(aaReal.y); Serial.print("\t"); Serial.println(aaReal.z); #endif #ifdef OUTPUT_READABLE_WORLDACCEL // display initial world-frame acceleration, adjusted to remove gravity // and rotated based on known orientation from quaternion mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); Serial.print("aworld\t"); Serial.print(aaWorld.x); Serial.print("\t"); Serial.print(aaWorld.y); Serial.print("\t"); Serial.println(aaWorld.z); #endif #ifdef OUTPUT_TEAPOT // display quaternion values in InvenSense Teapot demo format: teapotPacket[2] = fifoBuffer[0]; teapotPacket[3] = fifoBuffer[1]; teapotPacket[4] = fifoBuffer[4]; teapotPacket[5] = fifoBuffer[5]; teapotPacket[6] = fifoBuffer[8]; teapotPacket[7] = fifoBuffer[9]; teapotPacket[8] = fifoBuffer[12]; teapotPacket[9] = fifoBuffer[13]; Serial.write(teapotPacket, 14); teapotPacket[11]++; // packetCount, loops at 0xFF on purpose #endif // blink LED to indicate activity // BSP_LED_Toggle(LED3); } } }
void DMP::initialize(){ //This routine waits for the yaw angle to stop //drifting if (!dmpReady) return; printf("Initializing IMU...\n"); //float gyr_old = 10; int n=0; do { // wait for FIFO count > 42 bits do { fifoCount = mpu.getFIFOCount(); }while (fifoCount<42); if (fifoCount >= 1024) { // reset so we can continue cleanly mpu.resetFIFO(); printf("FIFO overflow!\n"); // otherwise, check for DMP data ready interrupt //(this should happen frequently) } else { //save old yaw value //gyr_old = gyro[ROLL]; //read packet from fifo mpu.getFIFOBytes(fifoBuffer, packetSize); mpu.dmpGetGyro(g, fifoBuffer); //0=gyroX, 1=gyroY, 2=gyroZ //swapped to match Yaw,Pitch,Roll //Scaled from deg/s to get tr/s for (int i=0;i<DIM;i++){ gyro[i] = (float)(g[DIM-i-1])/131.0/360.0; } // mpu.dmpGetQuaternion(&q, fifoBuffer); // mpu.dmpGetGravity(&gravity, &q); // mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); // // printf("yaw = %f, pitch = %f, roll = %f\n", // // ypr[YAW]*180/M_PI, ypr[PITCH]*180/M_PI, // // ypr[ROLL]*180/M_PI); } n++; }while (fabs(gyro[ROLL]) + fabs(gyro[PITCH]) > 0.03 && n<5000); mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); for (int i=0;i<DIM;i++) m_ypr_off[i] = ypr[i]; printf("IMU init done; offset values are :\n"); printf("yaw = %f, pitch = %f, roll = %f, n= %d\n\n", ypr[YAW]*180/M_PI, ypr[PITCH]*180/M_PI, ypr[ROLL]*180/M_PI,n); initialized = true; }
void loop() { // if programming failed, don't try to do anything if (!dmpReady) return; Serial.println("fireeer!"); // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { // other program behavior stuff here // . // . // . // if you are really paranoid you can frequently test in between other // stuff to see if mpuInterrupt is true, and if so, "break;" from the // while() loop to immediately process the MPU data // . // . // . // harry: try to reset here Serial.println("hang? reset!"); mpu.reset(); } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); Serial.println("FIFO overflow!"); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; #ifdef OUTPUT_READABLE_QUATERNION // display quaternion values in easy matrix form: w x y z mpu.dmpGetQuaternion(&q, fifoBuffer); Serial.print("quat\t"); Serial.print(q.w); Serial.print("\t"); Serial.print(q.x); Serial.print("\t"); Serial.print(q.y);; Serial.print("\t"); Serial.println(q.z); quaternionW = q.w; #endif #ifdef OUTPUT_READABLE_EULER // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetEuler(euler, &q); Serial.print("euler\t"); Serial.print(euler[0] * 180/M_PI); Serial.print("\t"); Serial.print(euler[1] * 180/M_PI); Serial.print("\t"); Serial.println(euler[2] * 180/M_PI); #endif #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); Serial.print("ypr\t"); Serial.print(ypr[0] * 180/M_PI); Serial.print("\t"); Serial.print(ypr[1] * 180/M_PI); Serial.print("\t"); Serial.println(ypr[2] * 180/M_PI); #endif #ifdef OUTPUT_READABLE_REALACCEL // display real acceleration, adjusted to remove gravity mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); Serial.print("areal\t"); Serial.print(aaReal.x); Serial.print("\t"); Serial.print(aaReal.y); Serial.print("\t"); Serial.println(aaReal.z); #endif #ifdef OUTPUT_READABLE_WORLDACCEL // display initial world-frame acceleration, adjusted to remove gravity // and rotated based on known orientation from quaternion mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); Serial.print("aworld\t"); Serial.print(aaWorld.x); Serial.print("\t"); Serial.print(aaWorld.y); Serial.print("\t"); Serial.println(aaWorld.z); #endif #ifdef OUTPUT_TEAPOT // display quaternion values in InvenSense Teapot demo format: teapotPacket[2] = fifoBuffer[0]; teapotPacket[3] = fifoBuffer[1]; teapotPacket[4] = fifoBuffer[4]; teapotPacket[5] = fifoBuffer[5]; teapotPacket[6] = fifoBuffer[8]; teapotPacket[7] = fifoBuffer[9]; teapotPacket[8] = fifoBuffer[12]; teapotPacket[9] = fifoBuffer[13]; Serial.write(teapotPacket, 14); teapotPacket[11]++; // packetCount, loops at 0xFF on purpose #endif // blink LED to indicate activity blinkState = !blinkState; digitalWrite(LED_PIN, blinkState); } }
bool Gyro_calibrate(uint16_t max_time) { uint32_t start_time = millis(); /* how many value differences were in range VALUE_RANGE */ uint16_t counter[3] = { 0, 0, 0 }; while (true) { /* waiting for interrupt */ while (!mpu_interrupt) { /* checking if function doesn't take longer than it should */ if (millis() - start_time > max_time) { return false; } } mpu_interrupt = false; mpuIntStatus = mpu.getIntStatus(); fifoCount = mpu.getFIFOCount(); /* owerflowed FIFO buffer (this should happen never) */ if ((mpuIntStatus & 0x10) || fifoCount == 1024) { mpu.resetFIFO(); } /* we can read data */ else if (mpuIntStatus & 0x02) { mpu.getFIFOBytes(fifoBuffer, packetSize); /* loop control variable */ uint8_t i; /* true if all indexes of counter[3] are >= COUNTER_RANGE */ bool calibrated; /* storing old data */ for (i = 0; i < 3; i++) { last_ypr[i] = ypr[i]; } /* getting new data */ mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); /* finding out, if we are "calibrated" */ calibrated = true; for (i = 0; i < 3; i++) { /* convert radians to degrees */ ypr[i] = ypr[i] * 180 / M_PI; if (abs(ypr[i] - last_ypr[i]) < VALUE_RANGE) { counter[i]++; if (counter[i] < COUNTER_RANGE) { calibrated = false; } } else { counter[i] = 0; } } /* if we are calibrate, set offsets and return true */ if (calibrated == true) { for (i = 0; i < 0; i++) { ypr_offsets[i] = ypr[i] * -1; } return true; } } } }
void* gyro_acc(void*) { //float kp = 0.00375,ki = 0.0000,kd = 0.00076; float kp = 0.0068,ki = 0.000,kd = 0.0018; //0030 0088 0014 有偏角 p0.0031偏角更大 0.0029也是 i=0 小偏角 p0.00305 d0.00143 不错 i0.0005 偏角变大 //0032 0017 float pregyro =0; float desired = 0; //double error; float integ=0;//integral积分参数 float iLimit =8 ; float deriv=0;//derivative微分参数 float prevError=0; float lastoutput=0; //float Piddeadband=0.3; // initialize device printf("Initializing I2C devices...\n"); mpu.initialize(); // verify connection printf("Testing device connections...\n"); printf(mpu.testConnection() ? "MPU6050 connection successful\n" : "MPU6050 connection failed\n"); mpu.setI2CMasterModeEnabled(false); mpu.setI2CBypassEnabled(true); // load and configure the DMP printf("Initializing DMP...\n"); devStatus = mpu.dmpInitialize(); // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it's ready printf("Enabling DMP...\n"); mpu.setDMPEnabled(true); // enable Arduino interrupt detection //Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); //attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it printf("DMP ready!\n"); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) printf("DMP Initialization failed (code %d)\n", devStatus); } /*****************************************************/ while(1) { if (START_FLAG == 0) { delay(200); } if (START_FLAG == 1) { break; } } delay(50); for(;;) { if (!dmpReady) return 0; // get current FIFO count fifoCount = mpu.getFIFOCount(); if (fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); printf("FIFO overflow!\n"); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (fifoCount >= 42) { // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //printf("ypr %7.2f %7.2f %7.2f ", ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI); Angle[2] = ypr[0] * 180/M_PI; Angle[1] = ypr[1] * 180/M_PI;//此为Pitch Angle[0] = ypr[2] * 180/M_PI;//此为Roll // display initial world-frame acceleration, adjusted to remove gravity // and rotated based on known orientation from quaternion mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); //printf("aworld %6d %6d %6d ", aaWorld.x, aaWorld.y, aaWorld.z); AngleSpeed[0] = aaWorld.x; AngleSpeed[1] = aaWorld.y; AngleSpeed[2] = aaWorld.z; /****************************读取完毕*********************************/ error = desired - Angle[0];//偏差:期望-测量值 All_Count = All_Count + 1; error = error * 0.88 + prevError * 0.12; /* if (fabs(prevError - error ) > 12) { error = prevError; }*/ integ += error * IMU_UPDATE_DT;//偏差积分,IMU_UPDATE_DT也就是每调整漏斗大小的步辐 if (integ >= iLimit)//作积分限制 { integ = iLimit; } else if (integ < -iLimit) { integ = -iLimit; } deriv = (error - prevError) / IMU_UPDATE_DT;//微分 应该可用陀螺仪角速度代替 AngleSpeed[0] = deriv; if (fabs(deriv) < 20 ) { if (fabs(deriv) < 10 ) { deriv = deriv * 0.8; } else { deriv = deriv * 0.9; } } //if(deriv //roll.deriv = -gyro;//注意是否跟自己的参数方向相反,不然会加剧振荡 //deriv = -AngleSpeed[0]; /* if (fabs(pregyro - deriv) > 20) { deriv = deriv * 0.5 + pregyro * 0.5; } */ output = (kp * error) + (ki * integ) + (kd * deriv); prevError = error;//更新前一次偏差 pregyro = deriv; if (output > 0.16) { output = 0.16; } if (output < -0.16) { output = -0.16; } Pid_Roll = output; //output = output * 0.9 + lastoutput * 0.1; if (fabs(error) < 0.3 ) { output = lastoutput * 0.5; } lastoutput = output; DutyCycle[0] = Default_Acc - output; DutyCycle[1] = Default_Acc - output; //DutyCycle[0] = Default_Acc; //DutyCycle[1] = Default_Acc; DutyCycle[2] = Default_Acc + output; DutyCycle[3] = Default_Acc + output; //DutyCycle[2] = Default_Acc; //DutyCycle[3] = Default_Acc; PWMOut(PinNumber1,DutyCycle[0]); PWMOut(PinNumber2,DutyCycle[1]); PWMOut(PinNumber3,DutyCycle[2]); PWMOut(PinNumber4,DutyCycle[3]); } } }
//void normalize_hmc(int16_t mag_val[3], float normalized[3]) { // float xn = mag_val[0] - 14.9727; // float yn = mag_val[1] + 156.7135; // float zn = mag_val[2] - 27.9874; // // normalized[0] = (0.9622 * xn + 0.0210 * yn + 0.0111 * zn) / 625.2703; // normalized[1] = (0.0210 * xn + 1.0454 * yn + 0.0030 * zn) / 625.2703; // normalized[2] = (0.0111 * xn + 0.0030 * yn + 0.9947 * zn) / 625.2703; //} // //void normalize_mpu(int16_t mag_val[3], float normalized[3]) { // float xn = mag_val[0] + 44.9175; // float yn = mag_val[1] + 25.3482; // float zn = mag_val[2] - 20.9063; // // // normalize *and* re-align axes (because, you know, having all sensors be the same is too much to ask for). // normalized[1] = ( 0.9878 * xn + 0.0102 * yn - 0.0040 * zn) / 146.4961; // normalized[0] = ( 0.0102 * xn + 0.9619 * yn - 0.0024 * zn) / 146.4961; // normalized[2] = - (-0.0040 * xn - 0.0024 * yn + 1.0526 * zn) / 146.4961; //} // int readHeading(float f_ypr[3]) { // if programming failed, don't try to do anything if (!dmpReady) return 0; // reset interrupt flag and get INT_STATUS byte mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) while ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); // do this again. // reset interrupt flag and get INT_STATUS byte mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); } while (!(mpuIntStatus & 0x02)) { mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); } // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; mpu.dmpGetMag(mag, fifoBuffer); if (abs(mag[0] > 255) || abs(mag[0] > 255) || abs(mag[0] > 255)) return 0; #ifdef CALIBRATE_ONLY logln(", %d, %d, %d", mag[0], mag[1], mag[2]); #else mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); float mpu_mag_out[3]; normalize_mpu(mag, mpu_mag_out); float magnetom[3]; for (int i=0; i<3; i++) magnetom[i] = mpu_mag_out[i]; float magComp[3]; float cos_pitch = cos(-ypr[1]); float sin_pitch = sin(-ypr[1]); float cos_roll = cos(ypr[2]); float sin_roll = sin(ypr[2]); // Tilt compensated magnetic field X float mag_x = magnetom[0] * cos_pitch + magnetom[1] * sin_roll * sin_pitch + magnetom[2] * cos_roll * sin_pitch; // Tilt compensated magnetic field Y float mag_y = magnetom[1] * cos_roll - magnetom[2] * sin_roll; // Magnetic Heading float heading = atan2(-mag_y, mag_x); f_ypr[0] = heading; f_ypr[1] = -ypr[1]; f_ypr[2] = ypr[2]; #endif return 1; }
int main() { // Setup IMU to get DMP data setup(); usleep(100000); if (!bcm2835_init()) { return 1; } bcm2835_spi_begin(); bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, 0); bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS1, 0); bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256); //4096); //2048); bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); bcm2835_spi_chipSelect(BCM2835_SPI_CS0); int var = 0; uint8_t imu_buf[BUF_SIZE]; for (var = 0; var < BUF_SIZE; var++) { imu_buf[var] = 0x00; } char * lcd_buf = getBitmap(); char RX = '0'; char TX = '0'; int i = 0; int ct = 0; int err = 0; int op_err = 0; int packets = 0; int seconds = 0; unsigned char bat1 = 0; unsigned char bat2 = 0; int data_p = 0; printf("Begin\n"); while (1) { clock_t total = clock(); // Establishing communication for getting battery data /* TX = BAT; RX = bcm2835_spi_transfer(TX); RX = bcm2835_spi_transfer(TX); while (RX != BAT) { op_err++; usleep(10000); RX = bcm2835_spi_transfer(TX); printf("| tx:%x rx:%x(%c) |", TX, RX, RX); if (op_err % 10 == 0) printf("\n"); } RX = bcm2835_spi_transfer(TX); bat1 = RX; RX = bcm2835_spi_transfer(TX); bat2 = RX; */ // battery status is stored in bat1 and bat2 data_p = 0; //trasnferring 1024 bytes of data: 12 at a time while (data_p < BUF_SIZE) { TX = ACCEL; RX = bcm2835_spi_transfer(TX); RX = bcm2835_spi_transfer(TX); while (RX != ACCEL) { op_err++; usleep(10000); RX = bcm2835_spi_transfer(TX); printf("| tx:%x rx:%x(%c) |", TX, RX, RX); if (op_err % 10 == 0) printf("\n"); } //printf("%d:Bat: %d%% %f Data: ", data_p, bat1, (bat1 + (float) bat2 / 256)); for (i = 0; i < CHUNK_SIZE; i++) { TX = lcd_buf[data_p + i]; RX = bcm2835_spi_transfer(TX); imu_buf[data_p + i] = RX; //printf("%x ", RX); } /* int x = (imu_buf[data_p + 0] << 8) | imu_buf[data_p + 1]; int y = (imu_buf[data_p + 2] << 8) | imu_buf[data_p + 3]; int z = (imu_buf[data_p + 4] << 8) | imu_buf[data_p + 5]; int gx = (imu_buf[data_p + 6] << 8) | imu_buf[data_p + 7]; int gy = (imu_buf[data_p + 8] << 8) | imu_buf[data_p + 9]; int gz = (imu_buf[data_p + 10] << 8) | imu_buf[data_p + 11]; printf("\nax:%d y:%d z:%d. gx:%d y:%d z:%d\n", x, y, z, gx, gy, gz); */ TX = VALID; RX = bcm2835_spi_transfer(TX); if (RX == VALID) { data_p += CHUNK_SIZE; } else{ printf("Invalid\n"); } mpu.dmpGetQuaternion(&q, &imu_buf[data_p-CHUNK_SIZE]); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); if(packets%10==5){ printf("ypr %7.2f %7.2f %7.2f ", ypr[0] * 180 / M_PI, ypr[1] * 180 / M_PI, ypr[2] * 180 / M_PI); float diffsec = (float) (clock() - total) / CLOCKS_PER_SEC; printf("ERR %d|| total time = %f\n", op_err, diffsec); } // gettimeofday(&tval_after, NULL); // timersub(&tval_after, &tval_before, &tval_result); // printf(" ---- transfer time %ld.%06ld sec", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec); // ct++; // printf("\n"); //if(packets%100==0) usleep(TIME_BETWEEN_CHUNK); } // printf("PACKET %d successfully transferred\n", packets); packets++; usleep(TIME_BETWEEN_BUF); lcd_buf = getBitmap(); } bcm2835_spi_end(); bcm2835_close(); }
void* gyro_acc(void*) { int i = 0; // initialize device printf("Initializing I2C devices...\n"); mpu.initialize(); // verify connection printf("Testing device connections...\n"); printf(mpu.testConnection() ? "MPU6050 connection successful\n" : "MPU6050 connection failed\n"); mpu.setI2CMasterModeEnabled(false); mpu.setI2CBypassEnabled(true); // load and configure the DMP printf("Initializing DMP...\n"); devStatus = mpu.dmpInitialize(); // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it's ready printf("Enabling DMP...\n"); mpu.setDMPEnabled(true); // enable Arduino interrupt detection //Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); //attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it printf("DMP ready!\n"); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) printf("DMP Initialization failed (code %d)\n", devStatus); return 0; } /*****************************************************/ while(1) { if (START_FLAG == 0) { delay(200); } if (START_FLAG == 1) { break; } } delay(50); for(;;) { if (!dmpReady) return 0; // get current FIFO count fifoCount = mpu.getFIFOCount(); if (fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); printf("FIFO overflow!\n"); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (fifoCount >= 42) { // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //printf("ypr %7.2f %7.2f %7.2f ", ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI); Angle[2] = ypr[0] * 180/M_PI; Angle[1] = ypr[1] * 180/M_PI;//此为Pitch Angle[0] = ypr[2] * 180/M_PI;//此为Roll // display initial world-frame acceleration, adjusted to remove gravity // and rotated based on known orientation from quaternion /* mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); //printf("aworld %6d %6d %6d ", aaWorld.x, aaWorld.y, aaWorld.z); //AngleSpeed[0] = aaWorld.x; //AngleSpeed[1] = aaWorld.y; //AngleSpeed[2] = aaWorld.z; */ /****************************读取完毕*********************************/ if (Inital <= 300) { Inital ++; if (Inital % 98 == 1) { Inital_Roll[i] = Angle[0]; Inital_Pitch[i] = Angle[1]; Inital_Yaw[i] = Angle[2]; printf("Roll:%.2f Pitch:%.2f Yaw:%.2f",Inital_Roll[i],Inital_Pitch[i],Inital_Yaw[i]); i++; printf("%d\n",Inital); fflush(stdout); if (i == 3) { Inital_Yaw[3] = (Inital_Yaw[0] + Inital_Yaw[1] + Inital_Yaw[2]) / 3; Inital_Roll[3] =(Inital_Roll[0] + Inital_Roll[1] + Inital_Roll[2]) / 3; Inital_Pitch[3] = (Inital_Pitch[0] + Inital_Pitch[1] + Inital_Pitch[2]) / 3; } } } else { Pid_Roll = Pid_Calc_R(Roll_Suit,Angle[0]); Pid_Pitch = Pid_Calc_P(Pitch_Suit,Angle[1]); Pid_Yaw = Pid_Calc_Y(Yaw_Suit,Angle[2],Inital_Yaw[3]); All_Count = All_Count + 1; DutyCycle[0] = Default_Acc - Pid_Roll - Pid_Pitch; //- Pid_Yaw; DutyCycle[1] = Default_Acc - Pid_Roll + Pid_Pitch; //+ Pid_Yaw; //DutyCycle[0] = Default_Acc; //DutyCycle[1] = Default_Acc; DutyCycle[2] = Default_Acc + Pid_Roll - Pid_Pitch; //+ Pid_Yaw; DutyCycle[3] = Default_Acc + Pid_Roll + Pid_Pitch; //- Pid_Yaw; //DutyCycle[2] = Default_Acc; //DutyCycle[3] = Default_Acc; PWMOut(PinNumber1,DutyCycle[0]); PWMOut(PinNumber2,DutyCycle[1]); PWMOut(PinNumber3,DutyCycle[2]); PWMOut(PinNumber4,DutyCycle[3]); } } } }
void loop() { // if programming failed, don't try to do anything if (!b_dmp_ready) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && uh_fifo_count < uh_packet_size) { } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; ua_mpu_interrupt_status = mpu.getIntStatus(); // get current FIFO count uh_fifo_count = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((ua_mpu_interrupt_status & 0x10) || uh_fifo_count == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); send_status(FIFO_OVERFLOW, ua_mpu_interrupt_status); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (ua_mpu_interrupt_status & 0x02) { uint8_t ua_idx, ua_nb = 0; uint8_t ua_data_len = 1; uint8_t ua_types = 0; uint8_t *pua_buf, *pua_data_buf, *pua_data_start; // wait for correct available data length, should be a VERY short wait while (uh_fifo_count < uh_packet_size) { uh_fifo_count = mpu.getFIFOCount(); } // read a packet from FIFO mpu.getFIFOBytes(ua_fifo_buffer, uh_packet_size); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) uh_fifo_count -= uh_packet_size; #ifdef OUTPUT_BUFFER ua_data_len += BUFFER_SIZE; ua_types |= OUTPUT_BUFFER; #else // display quaternion values in easy matrix form: w x y z mpu.dmpGetQuaternion(&s_quaternion, ua_fifo_buffer); #endif #ifdef OUTPUT_QUATERNION ua_data_len += 4 * sizeof(float); ua_types |= OUTPUT_QUATERNION; #endif #ifdef OUTPUT_EULER mpu.dmpGetEuler(rf_euler, &s_quaternion); ua_data_len += 3 * sizeof(float); ua_types |= OUTPUT_EULER; #endif #if defined(OUTPUT_YAWPITCHROLL) || defined(OUTPUT_REALACCEL) || defined(OUTPUT_WORLDACCEL) mpu.dmpGetGravity(&s_gravity, &s_quaternion); #endif #ifdef OUTPUT_YAWPITCHROLL mpu.dmpGetYawPitchRoll(rf_ypr, &s_quaternion, &s_gravity); ua_data_len += 3 * sizeof(float); ua_types |= OUTPUT_YAWPITCHROLL; #endif #if defined(OUTPUT_REALACCEL) || defined(OUTPUT_WORLDACCEL) // display real acceleration, adjusted to remove gravity mpu.dmpGetAccel(&s_acceleration, ua_fifo_buffer); mpu.dmpGetLinearAccel(&s_acceleration_real, &s_acceleration, &s_gravity); #endif #ifdef OUTPUT_REALACCEL ua_data_len += 3 * sizeof(float); ua_types |= OUTPUT_REALACCEL; #endif #ifdef OUTPUT_WORLDACCEL // display initial world-frame acceleration, adjusted to remove gravity mpu.dmpGetLinearAccelInWorld(&s_acceleration_world, &s_acceleration_real, &s_quaternion); ua_data_len += 3 * sizeof(float); ua_types |= OUTPUT_WORLDACCEL; #endif // allocate the buffe to store the values pua_data_start = (uint8_t*)malloc(ua_data_len); // Store the start of the buffer pua_data_buf = pua_data_start; // Setup type of data expected *pua_data_buf++ = ua_types; #ifdef OUTPUT_BUFFER *pua_data_buf++ = ua_fifo_buffer[0]; *pua_data_buf++ = ua_fifo_buffer[1]; *pua_data_buf++ = ua_fifo_buffer[4]; *pua_data_buf++ = ua_fifo_buffer[5]; *pua_data_buf++ = ua_fifo_buffer[8]; *pua_data_buf++ = ua_fifo_buffer[9]; *pua_data_buf++ = ua_fifo_buffer[12]; *pua_data_buf++ = ua_fifo_buffer[13]; #endif #ifdef OUTPUT_QUATERNION pua_data_buf += store_float32(pua_data_buf, s_quaternion.w); pua_data_buf += store_float32(pua_data_buf, s_quaternion.x); pua_data_buf += store_float32(pua_data_buf, s_quaternion.y); pua_data_buf += store_float32(pua_data_buf, s_quaternion.z); #endif #ifdef OUTPUT_EULER pua_data_buf += store_float32(pua_data_buf, rf_euler[0] * 180/M_PI); pua_data_buf += store_float32(pua_data_buf, rf_euler[1] * 180/M_PI); pua_data_buf += store_float32(pua_data_buf, rf_euler[2] * 180/M_PI); #endif #ifdef OUTPUT_YAWPITCHROLL pua_data_buf += store_float32(pua_data_buf, rf_ypr[0] * 180/M_PI); pua_data_buf += store_float32(pua_data_buf, rf_ypr[1] * 180/M_PI); pua_data_buf += store_float32(pua_data_buf, rf_ypr[2] * 180/M_PI); #endif #ifdef OUTPUT_REALACCEL pua_data_buf += store_float32(pua_data_buf, s_acceleration_real.x); pua_data_buf += store_float32(pua_data_buf, s_acceleration_real.y); pua_data_buf += store_float32(pua_data_buf, s_acceleration_real.z); #endif #ifdef OUTPUT_WORLDACCEL pua_data_buf += store_float32(pua_data_buf, s_acceleration_world.x); pua_data_buf += store_float32(pua_data_buf, s_acceleration_world.y); pua_data_buf += store_float32(pua_data_buf, s_acceleration_world.z); #endif // send the result pua_buf = frame_get((uint8_t*)pua_data_start, ua_data_len); if (pua_buf != NULL) { Serial.write(pua_buf, FULL_SIZE + ua_data_len); free(pua_buf); } free(pua_data_start); // blink LED to indicate activity b_blink_state = !b_blink_state; digitalWrite(LED_PIN, b_blink_state); } }
void loop() { // if programming failed, don't try to do anything if (!dmpReady) return; // get current FIFO count fifoCount = mpu.getFIFOCount(); if (fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); printf("FIFO overflow!\n"); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (fifoCount >= 42) { // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); #ifdef OUTPUT_READABLE_QUATERNION // display quaternion values in easy matrix form: w x y z mpu.dmpGetQuaternion(&q, fifoBuffer); printf("quat %7.2f %7.2f %7.2f %7.2f ", q.w,q.x,q.y,q.z); #endif #ifdef OUTPUT_READABLE_EULER // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetEuler(euler, &q); printf("euler %7.2f %7.2f %7.2f ", euler[0] * 180/M_PI, euler[1] * 180/M_PI, euler[2] * 180/M_PI); #endif #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); printf("ypr %7.2f %7.2f %7.2f ", ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI); #endif #ifdef OUTPUT_READABLE_REALACCEL // display real acceleration, adjusted to remove gravity mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); printf("areal %6d %6d %6d ", aaReal.x, aaReal.y, aaReal.z); #endif #ifdef OUTPUT_READABLE_WORLDACCEL // display initial world-frame acceleration, adjusted to remove gravity // and rotated based on known orientation from quaternion mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); printf("aworld %6d %6d %6d ", aaWorld.x, aaWorld.y, aaWorld.z); #endif #ifdef OUTPUT_TEAPOT // display quaternion values in InvenSense Teapot demo format: teapotPacket[2] = fifoBuffer[0]; teapotPacket[3] = fifoBuffer[1]; teapotPacket[4] = fifoBuffer[4]; teapotPacket[5] = fifoBuffer[5]; teapotPacket[6] = fifoBuffer[8]; teapotPacket[7] = fifoBuffer[9]; teapotPacket[8] = fifoBuffer[12]; teapotPacket[9] = fifoBuffer[13]; Serial.write(teapotPacket, 14); teapotPacket[11]++; // packetCount, loops at 0xFF on purpose #endif printf("\n"); } }
void imu_read() { uint8_t count = 3; // if programming failed, don't try to do anything if (!dmpReady) return; #ifdef IRQ_DEBUG #ifdef __BOARD_YUN__ Console.println(F("DMP is ready!\nAwaiting for IRQ ready flag")); #else Serial.println(F("DMP is ready!\nAwaiting for IRQ ready flag")); #endif #endif // wait for MPU interrupt or extra packet(s) available /* while (!mpuInterrupt && fifoCount < packetSize) { // Serial.println("Shouldn't get here..."); } Serial.println("DMP flag OK"); */ while(!mpuInterrupt && fifoCount < packetSize) ; // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); #ifdef __BOARD_YUN__ Console.println(F("FIFO overflow!")); #else Serial.println(F("FIFO overflow!")); #endif // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); #ifdef __USE_ANTILOCK__ if(lastQ == q) { if(--count) { #ifdef __BOARD_YUN__ Console.println(F("\nLOCKED\n")); dmpReady = false; Console.println(F("DMP is stalled, reinitializing...")); #else Serial.println(F("\nLOCKED\n")); dmpReady = false; Serial.println(F("DMP stalled, reinitializing...")); #endif mpu.reset(); if ((devStatus = mpu.dmpInitialize()) == 0) { mpu.setDMPEnabled(true); mpuIntStatus = mpu.getIntStatus(); dmpReady = true; packetSize = mpu.dmpGetFIFOPacketSize(); } else { #ifdef __BOARD_YUN__ Console.print(F("DMP reinitialization failed (code ")); Console.print(devStatus); Console.println(F(")")); #else Serial.print(F("DMP reinitialization failed (code ")); Serial.print(devStatus); Serial.println(")"); #endif while (true) { //delay(300); //nilThdSleep(300); sleep(300); digitalWrite(SOL_LED, 0); //delay(300); //nilThdSleep(300); sleep(300); digitalWrite(SOL_LED, 1); } } } } #endif } else { #ifdef IRQ_DEBUG #ifdef __BOARD_YUN__ Console.print(F("OK")); #else Serial.print(F("OK ")); #endif #endif count = 3; lastQ = q; mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); mpu.dmpGetGyro(gyro, fifoBuffer); #ifdef DEBUG #ifdef __BOARD_YUN__ Console.print(F("ypr gyro\t")); Console.print(ypr[0] * 180/M_PI); Console.print(F("\t")); Console.print(ypr[1] * 180/M_PI); Console.print(F("\t")); Console.print(ypr[2] * 180/M_PI); Console.print(F("\t")); Console.println(gyro); #else Serial.print(F("ypr gyro\t")); Serial.print(ypr[0] * 180/M_PI); Serial.print(F("\t")); Serial.print(ypr[1] * 180/M_PI); Serial.print(F("\t")); Serial.print(ypr[2] * 180/M_PI); Serial.print(F("\t")); Serial.println(gyro); #endif #endif } // blink LED to indicate activity blinkState = !blinkState; digitalWrite(SOL_LED, blinkState); //delay(1); //nilThdSleep(1); sleep(1); }