int main(int argc, char const *argv[]) { AccelVector gravity; MPU6050 accelgyro; accelgyro.initialize(); accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_2); int16_t x=-3940, y=-0110, z=00326; int16_t gx, gy, gz; // accelgyro.getAcceleration(&x, &y,&z); gravity.x = x; gravity.y = y; gravity.z = z; float alpha = 0.5f, gyralpha = 0.9f; // for(int i=0; i<100; i++){ // accelgyro.getAcceleration(&x, &y,&z); // gravity.x = gravity.x * alpha + x * (1 - alpha); // gravity.y = gravity.y * alpha + y * (1 - alpha); // gravity.z = gravity.z * alpha + z * (1 - alpha); // usleep(50000); // } AccelVector vec, gyr; accelgyro.getMotion6(&x, &y,&z, &gx, &gy, &gz); gyr.x = gx; gyr.y = gy; gyr.z = gz; while(1) { accelgyro.getMotion6(&x, &y,&z, &gx, &gy, &gz); //accelgyro.getAcceleration(&x, &y,&z,); vec.x = vec.x * alpha + x * (1 - alpha); vec.y = vec.y * alpha + y * (1 - alpha); vec.z = vec.z * alpha + z * (1 - alpha); gyr.x = gyr.x * gyralpha + gx * (1 - gyralpha); gyr.y = gyr.y * gyralpha + gy * (1 - gyralpha); gyr.z = gyr.z * gyralpha + gz * (1 - gyralpha); printf("Total gforce now %.3f g's gyro len %.3f | Now: %05.0f %05.0f %05.0f Gyro: %05.0f %05.0f %05.0f\n", vec.getMagnitude()/16000, gyr.getMagnitude(), vec.x, vec.y, vec.z, gyr.x, gyr.y, gyr.z); usleep(50000); } // MPU control/status vars /*bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer // orientation/motion vars Quaternion q; // [w, x, y, z] quaternion container VectorInt16 aa; // [x, y, z] accel sensor measurements VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector float euler[3]; // [psi, theta, phi] Euler angle container float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector MPU6050 accelgyro; accelgyro.initialize(); // load and configure the DMP printf("Initializing DMP...\n"); devStatus = accelgyro.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"); accelgyro.setDMPEnabled(true); // enable Arduino interrupt detection //Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); //attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = accelgyro.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 = accelgyro.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){ fifoCount = accelgyro.getFIFOCount(); if (fifoCount == 1024) { // reset so we can continue cleanly accelgyro.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 accelgyro.getFIFOBytes(fifoBuffer, packetSize); // display Euler angles in degrees accelgyro.dmpGetQuaternion(&q, fifoBuffer); accelgyro.dmpGetGravity(&gravity, &q); accelgyro.dmpGetYawPitchRoll(ypr, &q, &gravity); printf("ypr %7.2f %7.2f %7.2f \n", ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI); } } */ return 0; }
int main() { // MPU6050 object "MPU6050.h" MPU6050 accelgyro; // Kalman filter Object "Kalman.h" Kalman kalman; // Xbee serial baudrate xBee.baud(38400); pc.baud(9600); // Initialize timers Timer timer, code, encTimer; // Start timers timer.start(); code.start(); encTimer.start(); // Reset timer values timer.reset(); code.reset(); encTimer.reset(); //Encoder 1 interrupts enc1a.rise(&incrementEnc1a); enc1b.rise(&incrementEnc1b); enc1a.fall(&setEnc1aFall); enc1b.fall(&setEnc1bFall); enc2a.rise(&incrementEnc2a); enc2b.rise(&incrementEnc2b); enc2a.fall(&setEnc2aFall); enc2b.fall(&setEnc2bFall); // Debug leds myled1 = 0; myled2 = 0; myled3 = 0; // Encoder 1 initializations newTime =0; oldTime = 0; lastEncTime = 0; enc1Speed = 0; enc2Speed = 0; // MPU6050 initializations accelgyro.initialize(); accelgyro.setFullScaleGyroRange(0); accelgyro.setFullScaleAccelRange(0); // Initialize MotorShield object shield.init(); float measuredTheta , measuredRate, newTheta,calcRate; float position= 0, velocity = 0, lastPosition = 0, lastVelocity =0; float angleOffset = 0, positionOffset = 0,lastAngleoffset = 0; // Position control constants, if necessary float zoneA = 16000.0f, zoneB = 8000.0f, zoneC = 2000.0f; float multiplier = 1.0f; float zoneAscale = 600*2*multiplier, zoneBscale = 800*2*multiplier, zoneCscale = 1000*2*multiplier, zoneDscale = 1500*2*multiplier, velocityScale = 60*2*multiplier; // Serial communication buffer char buffer[40]; int i, strSize; // Control parameters float k0,k1,k2,k3,tref; float x, dotx, deltaX, deltaT, lastX = 0; // Helper variables float waittime , u, diff, dt; float error = 0,lastError = 0; int counter = 0; float pTerm = 0,dTerm = 0,iTerm = 0; while(1) { /////////////////////////////////////////// // Read serial data and update constants // /////////////////////////////////////////// i = 0; char a; while(pc.readable()){ a = pc.getc(); buffer[i++] = a; printf("%c\n", a ); myled1 = 1; wait(0.001); } strSize = i; string receive(buffer,strSize); // Changes from char to string if(strSize > 0){ printf("%s\n", receive); assignGainsFromString(&k[0], &k[1], &k[2], &k[3], &k[4],receive); } // Below is an attempt to control the robot position, // by dividing it into "zones" and changing the angle accordingly. // ///////////////////////////// // Generate encoder offset // ///////////////////////////// // position = (float)enc2total; // positionOffset = position; // //if((encTimer.read_us() - lastEncTime) > 0.0f ) { // every 100 ms // float sign = 0; // if(positionOffset > 0) sign= 1; // else sign = -1; // if(abs(positionOffset) > zoneA) angleOffset += 1.0f/zoneAscale*positionOffset; // else if(abs(positionOffset) > zoneB) angleOffset += 1.0f/zoneBscale*positionOffset; // else if(abs(positionOffset) > zoneC) angleOffset += 1.0f/zoneCscale*positionOffset; // else angleOffset += positionOffset/zoneDscale; // printf("angleOffset: %f, positionoffset: %f\n", angleOffset, positionOffset ); // // Estimate velocity // // // velocity = (position - lastPosition); // lastPosition = position; // angleOffset += velocity/velocityScale; // angleOffset = constrain(angleOffset,-10, 10); // lastAngleoffset = angleOffset; // //} // angleOffset = constrain(angleOffset,lastAngleoffset - 1, lastAngleoffset + 1); timer.reset(); /////////////////////////// // Get gyro/accel values // /////////////////////////// accelgyro.getAcceleration(&ax,&ay,&az); measuredRate = accelgyro.getRotationX()*1.0/131.0f; // Units depend on config. Right now 250o/s measuredTheta = -atan(1.0*ay/az); measuredTheta = measuredTheta*180/PI; // measured in degrees /////////////////// // Kalman Filter // /////////////////// dt = (double)(code.read_us() - oldTime)/1000000.0f; newTheta = kalman.getAngle(measuredTheta, -measuredRate, dt); //DEBUG: printf("%g \n", (double)(code.read_us() - oldTime)/1000000.0f); oldTime = code.read_us(); ////////////////// // Control loop // ////////////////// // Set control variable to zero u = 0; // Extract constants from k vector, which has the serial readings. float kp = k[0]; float ki = k[1]; float kd = k[2]; tref = k[3] - angleOffset; waittime = k[4]; if(newTheta >= 50 || newTheta <= -50){ u = 0; }else{ // Define error term error = newTheta - tref; // Proportional term pTerm = kp*error; //Integral term iTerm += ki*error*dt*100.0f; // Prevent integration windup: if(iTerm >= 100) iTerm = 100; else if (iTerm <= -100) iTerm = -100; u = -(iTerm + pTerm); // Calculated derivative based on smoothened angle. // There are two other sources for the angle here: kalman.getRate(); and measuredRate. calcRate = -(error-lastError)/dt; // Derivative term if(kd != 0) dTerm = kd*calcRate/100.0f; lastError = error; u += dTerm; // Correct for dead zone --- Did not have successful results but I'll leave it here. // int deadzone = 20; // if(u < -deadzone) u = u + deadzone; // else if(u > deadzone) u = u - deadzone; // else u = 0; // // Include saturation u = constrain(u,-400,400); // Flash LED to indicate loop if(counter % 50 == 0){ myled3 = !myled3; counter = 0; } counter++; } lastError = error; // update angle if(counter % 50 == 0){ myled3 = !myled3; // xBee.printf("%f,%f\n", newTheta,u); counter = 0; } // Set motor speed shield.setM1Speed(-(int)u); shield.setM2Speed((int)u); // DEBUG over serial port. Use with MATLAB program "serialPlot.m" to plot these results. printf("%f,%f,%f\n", measuredTheta, newTheta , u); // Hold the timer until desired sampling time is reached. while(timer.read_us() < waittime*1000); // Turn off serial transmission LED myled1 = 0; } }
// // main task // int main(void) { #ifdef DEBUG #if __USE_USB usbCDC ser; ser.connect(); #else CSerial ser; ser.settings(115200); #endif CDebug dbg(ser); dbg.start(); #endif /************************************************************************* * * your setup code here * **************************************************************************/ // // Load Configuration // EEPROM::read(0, &config, sizeof(config)); if ( config.length!=sizeof(config) ) { setDefault(); } // class default I2C address is 0x68 // specific I2C addresses may be passed as a parameter here // AD0 low = 0x68 (default for InvenSense evaluation board) // AD0 high = 0x69 MPU6050 mpu; // initialize device mpu.initialize(); mpu.setRate(7); mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_250); mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2); // // check device // if (mpu.testConnection()) { } // // H-Bridge // CPwm::frequency(KHZ(20)); HBridge left(PWM1, P18, P19); HBridge right(PWM2, P22, P23); left.enable(); right.enable(); BalanceRobot robot(mpu, left, right); robot.start("Robot", 168, PRI_HIGH); #ifndef DEBUG myMenu menu(mpu, robot); menu.start(); #endif while (1) { /********************************************************************** * * your loop code here * **********************************************************************/ LEDs[0] = !LEDs[0]; sleep(500); } return 0;