Last active
August 29, 2015 14:12
-
-
Save kcranley1/de807b7ed32cf8824808 to your computer and use it in GitHub Desktop.
Uses my implementation of the Complementary Filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python | |
| # KC6050Servos.py Reads MPU6050 and also drives 2 servos | |
| # Initially written by Adafruit and developed by S&S Dec 2014 | |
| import smbus | |
| import math | |
| import time | |
| from Adafruit_PWM_Servo_Driver import PWM | |
| # Initialise the PWM device using the default address | |
| pwm = PWM(0x40) | |
| # Note if you'd like more debug output you can instead run: | |
| #pwm = PWM(0x40, debug=True) | |
| servoMin = 150 # Min pulse length out of 4096 | |
| servoMax = 600 # Max pulse length out of 4096 | |
| # Power management registers | |
| power_mgmt_1 = 0x6b | |
| power_mgmt_2 = 0x6c | |
| # Chip temperature register | |
| temp = 0x41 | |
| celsius = (temp/340.00) + 36.53 | |
| print "Temp = ", "%.2f" % celsius, " deg C" # Just for fun! (Hope it's right!) | |
| def read_byte(adr): | |
| return bus.read_byte_data(address, adr) | |
| def read_word(adr): | |
| high = bus.read_byte_data(address, adr) | |
| low = bus.read_byte_data(address, adr+1) | |
| val = (high << 8) + low | |
| return val | |
| def read_word_2c(adr): | |
| val = read_word(adr) | |
| if (val >= 0x8000): | |
| return -((65535 - val) + 1) | |
| else: | |
| return val | |
| def dist(a,b): | |
| return math.sqrt((a*a)+(b*b)) | |
| def get_y_rotation(x,y,z): | |
| radians = math.atan2(x, dist(y,z)) | |
| return -math.degrees(radians) | |
| def get_x_rotation(x,y,z): | |
| radians = math.atan2(y, dist(x,z)) | |
| return math.degrees(radians) | |
| def setServoPulse(channel, pulse): | |
| pulseLength = 1000000 # 1,000,000 us per second | |
| pulseLength /= 60 # 60 Hz | |
| print "%d us per period" % pulseLength | |
| pulseLength /= 4096 # 12 bits of resolution | |
| print "%d us per bit" % pulseLength | |
| pulse *= 1000 | |
| pulse /= pulseLength | |
| pwm.setPWM(channel, 0, pulse) | |
| xrot = 0.0 | |
| yrot = 0.0 | |
| def read_data(): | |
| global xrot | |
| global yrot | |
| global xangvel | |
| global yangvel | |
| gyro_xout = read_word_2c(0x43) | |
| gyro_yout = read_word_2c(0x45) | |
| gyro_zout = read_word_2c(0x47) | |
| xangvel = gyro_xout / 131.0 # gyro angular velocity in degrees/second | |
| yangvel = gyro_yout / 131.0 | |
| zangvel = gyro_zout / 131.0 | |
| accel_xout = read_word_2c(0x3b) | |
| accel_yout = read_word_2c(0x3d) | |
| accel_zout = read_word_2c(0x3f) | |
| accel_xout_scaled = accel_xout / 16384.0 # accelerometer rotation rate deg/s | |
| accel_yout_scaled = accel_yout / 16384.0 | |
| accel_zout_scaled = accel_zout / 16384.0 | |
| xrot = get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled) | |
| yrot = get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled) | |
| def filtered_angle(gyro_angvel, accel_angle): | |
| # My implementation of the Complementary Filter | |
| delta_t = 0.003 # Approximate no of seconds each loop of the program takes | |
| taw = 0.001 # time constant of accelerometer noise (estimate in s) | |
| alpha = taw/(taw + delta_t) | |
| filteredAngle = (alpha * gyro_angvel * delta_t) + ((1-alpha)*accel_angle) | |
| return filteredAngle | |
| pwm.setPWMFreq(60) # Set frequency to 60 Hz | |
| bus = smbus.SMBus(1) # or bus = smbus.SMBus(1) for Revision 2 RasPis | |
| address = 0x68 # This is the address value read via the i2cdetect command | |
| # Now wake the 6050 up as it starts in sleep mode | |
| bus.write_byte_data(address, power_mgmt_1, 0) | |
| # Map servo rotation to MPU6050 orientation | |
| slope = (servoMax-servoMin)/180.0 | |
| middle = servoMin+(servoMax-servoMin)/2 | |
| pwm.setPWM(11, 0, middle) | |
| pwm.setPWM(15, 0, middle) | |
| while (True): | |
| read_data() | |
| pwm.setPWM(15, 0, middle+int(slope*filtered_angle(xangvel, xrot))) | |
| pwm.setPWM(11, 0, middle+int(slope*filtered_angle(yangvel, yrot))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment