Guest User

mega MPU6050 segway

a guest
Jun 3rd, 2013
1,348
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.04 KB | None | 0 0
  1. // CHRIS LONGBOTTOM BALANCING CODE FOR ARDUINO MEGA 2560 AND MPU6050, with BTS7960B controllers.
  2. #include "Wire.h"
  3. #include <math.h>
  4.  
  5. #include "I2Cdev.h"
  6. #include "MPU6050.h"
  7.  
  8. // class default I2C address is 0x68
  9. // specific I2C addresses may be passed as a parameter here
  10. // AD0 low = 0x68 (default for InvenSense evaluation board)
  11. // AD0 high = 0x69
  12. MPU6050 accelgyro;
  13.  
  14. int16_t ax, ay, az;
  15. int16_t gx, gy, gz;
  16.  
  17. #define LED_PIN 13
  18. bool blinkState = false;
  19.  
  20. #define ACCELEROMETER_SENSITIVITY 8192.0
  21. #define GYROSCOPE_SENSITIVITY 65.536
  22. #define M_PI 3.14159265359     
  23. #define dt 0.01
  24. #define MAX_ANGLE 25
  25.  
  26.  
  27. float angle = 0;
  28. float angle_old = 0;
  29. float angle_dydx = 0;
  30. float angle_integral = 0;
  31. float balancetorque = 0;
  32. float rest_angle = 0;
  33. float currentspeed = 0;
  34. int steeringZero = 0;
  35. int steering = 0;
  36. int steeringTemp = 0;
  37.  
  38. float p = 8; //2
  39. float i = 0; //0.005
  40. float d = 1300; //1000
  41.  
  42. float gyro_integration = 0;
  43. float xZero = 0;
  44. int gZero = 445; //this is always fixed, hence why no initialisation routine
  45.  
  46. int L_pwmL, L_pwmR;
  47. int R_pwmL, R_pwmR;
  48.  
  49. boolean over_angle = 0;
  50.  
  51. double accXangle, accYangle; // Angle calculate using the accelerometer
  52. double gyroXangle, gyroYangle; // Angle calculate using the gyro
  53. double compAngleX, compAngleY; // Calculate the angle using a complementary filter
  54.  
  55. float distance = 0;
  56.  
  57. float gyro_offset = 0, angle_offset = 0;
  58.  
  59. int LPWM = 2; // H-bridge leg 1 ->LPWM
  60. int enL = 8; // H-bridge enable pin 1 -> L_EN
  61.  
  62. int RPWM = 12; // H-bridge leg 2 ->RPWM
  63. int enR = 7; // H-bridge enable pin 2 -> R_EN
  64.  
  65. int pwm = 0;
  66.  
  67. uint32_t timer;
  68.  
  69. void setup() {
  70.  
  71.   pinMode(LPWM, OUTPUT);
  72.   pinMode(RPWM, OUTPUT);
  73.   pinMode(enL, OUTPUT);
  74.   pinMode(enR, OUTPUT);
  75.  
  76.   digitalWrite(enL, HIGH);
  77.   digitalWrite(enR, HIGH);
  78.   digitalWrite(LPWM, LOW);
  79.   digitalWrite(RPWM, LOW);
  80.  
  81.   /* LIST OF TIMERS FOR MEGA
  82.   timer 0 (controls pin 13, 4)
  83.   timer 1 (controls pin 12, 11)
  84.   timer 2 (controls pin 10, 9)
  85.   timer 3 (controls pin 5, 3, 2)
  86.   timer 4 (controls pin 8, 7, 6)
  87.   */
  88.  
  89.   // REGISTERS FOR TCCR1A and TCCR1B, same for others
  90.   // TCCR1A: COM1A1 COM2A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
  91.   // TCCR1B: ICNC1  ICES1    -    WGM13  WGM12  CS12   CS11  CS10
  92.  
  93.   TCCR1A = B01100001; // Fast PWM
  94.   TCCR1B = B10001; //no prescalering
  95.  
  96.   OCR1A = 639; //count to 639 (16MHz/(640-1)=25 kHz)
  97.  
  98.   TCCR3A = B01100001; // Fast PWM // PHASE CORRECT (with second bit of B register)
  99.   TCCR3B = B10001; //no prescalering
  100.  
  101.   OCR3A = 639; //count to 639 (16MHz/(640-1)=25 kHz)
  102.  
  103.     // join I2C bus (I2Cdev library doesn't do this automatically)
  104.     Wire.begin();
  105.  
  106.     // initialize serial communication
  107.     // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
  108.     // it's really up to you depending on your project)
  109.     Serial.begin(38400);
  110.  
  111.     // initialize device
  112.     //Serial.println("Initializing I2C devices...");
  113.     accelgyro.initialize();
  114.  
  115.     // verify connection
  116.     Serial.println("Testing device connections...");
  117.     Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  118.  
  119.     // configure Arduino LED for
  120.     pinMode(LED_PIN, OUTPUT);
  121.     if(accelgyro.testConnection())
  122.       digitalWrite(LED_PIN,HIGH);
  123.    
  124.     gyro_offset = 0;
  125.     angle_offset = 0;
  126.    
  127.     // GET OFFSET FOR INITIALISATION    
  128.     for(int z = 0;z<300;z++) {
  129.       //calculatei();
  130.       accelgyro.getAcceleration(&ax, &ay, &az);
  131.       angle_offset += ax;
  132.     }
  133.    
  134.     angle_offset=angle_offset/300;
  135.  
  136. }
  137.  
  138. void loop() {
  139.     // read raw accel/gyro measurements from device
  140.     accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  141.    
  142.     ax -= angle_offset;
  143.     gx -= gyro_offset;
  144.    
  145.     accXangle = (atan2(ay,az)+PI)*RAD_TO_DEG;
  146.     accYangle = (atan2(ax,az)+PI)*RAD_TO_DEG;
  147.    
  148.     if(accXangle > 180)
  149.       accXangle = accXangle-360;
  150.    
  151.     double gyroXrate = (double)gx/131.0;
  152.     double gyroYrate = -((double)gy/131.0);
  153.    
  154.     compAngleX = (0.98*(compAngleX+(gyroXrate*(double)(micros()-timer)/1000000)))+(0.02*accXangle); // Calculate the angle using a Complimentary filter
  155.     compAngleY = (0.98*(compAngleY+(gyroYrate*(double)(micros()-timer)/1000000)))+(0.02*accYangle);
  156.    
  157.     float motor = 45*compAngleX + 2.2*gyroXrate;
  158.    
  159.     // MAX PWM for BTS is 25kHz
  160.     // Max arduino write = 255...
  161.    
  162.     if(motor > 250) {
  163.      L_pwmL = 1;
  164.      L_pwmR = 250;
  165.      R_pwmL = 1;
  166.      R_pwmR = 250;
  167.    
  168.     analogWrite(RPWM,1);
  169.     OCR1B = 639;
  170.     digitalWrite(LPWM, LOW);
  171.    
  172.     } else if(motor < -250) {
  173.      L_pwmL = 250;
  174.      L_pwmR = 1;
  175.      R_pwmL = 250;
  176.      R_pwmR = 1;
  177.    
  178.     analogWrite(LPWM,1);
  179.     OCR3B = 639;
  180.     digitalWrite(RPWM, LOW);
  181.    
  182.     } else if(motor > 0) {
  183.      L_pwmL = 1;
  184.      L_pwmR = (int) (((motor)/255)*639);
  185.      R_pwmL = 1;
  186.      R_pwmR = (int) (((motor)/255)*639);
  187.    
  188.     analogWrite(RPWM,1);
  189.     OCR1B = R_pwmR;
  190.     digitalWrite(LPWM, LOW);
  191.    
  192.     } else {
  193.      L_pwmL = (int) ((abs((motor))/255)*639);
  194.      L_pwmR = 1;
  195.      R_pwmL = (int) ((abs((motor))/255)*639);
  196.      R_pwmR = 1;
  197.    
  198.     analogWrite(LPWM,1);
  199.     OCR3B = L_pwmL;
  200.     digitalWrite(RPWM, LOW);
  201.    
  202.     }
  203.    
  204.    
  205.     /* POTENTAIALL REACH A MAX ANGLE???
  206.     if(compAngleX > MAX_ANGLE) {
  207.      Serial.println("Reached max angle FORWARD");
  208.     } else if(compAngleX < MAX_ANGLE*-1) {
  209.      Serial.println("Reached max angle BACKWARD");
  210.     }
  211.     */
  212.    
  213.     gyroXangle += gyroXrate*((double)(micros()-timer)/1000000);
  214.    
  215.     timer = micros();
  216.    
  217.    
  218.     Serial.print(accXangle);    Serial.print("\t");
  219.     Serial.print(gyroXangle);    Serial.print("\t");
  220.     Serial.print(gyroXrate);    Serial.print("\t");
  221.     Serial.print(compAngleX);   Serial.print("\t\t");
  222.     Serial.print(motor);   Serial.print("\t\t");
  223.  
  224.     Serial.print(L_pwmL);   Serial.print("\t");
  225.     Serial.print(L_pwmR);   Serial.print("\t");
  226.    
  227.     Serial.println();
  228.    
  229.     // blink LED to indicate activity
  230.     blinkState = !blinkState;
  231.     digitalWrite(LED_PIN, blinkState);
  232. }
Advertisement
Add Comment
Please, Sign In to add comment