راه اندازی ماژول MPU6050 توسط رزبری پای

الکترونیک و رباتیک -> ماژول ها و سنسور ها 1681 6 کاربر آکادمی پارتینه

هدف از به کارگیری ماژول MPU6050 چیست؟
ماژول MPU6050 یک ماژول اینرسی شش‌محوره است که تلفیقی از ژیروسکوپ و شتاب‌سنج می‌باشد. سه محور اختصاص به شتاب زاویه‌ای و سه محور دیگر برای سنجش سرعت زاویه‌ای به کار گرفته می‌شود.

وجود پردازشگر حرکتی دیجیتال (DMP) در این ماژول به دلیل جمع‌آوری و پردازش داده‌ها از شتاب‌سنج و ژیروسکوپ باعث شده تا بار محاسباتی از پردازشگر میزبان، مانند آردوینو و ... کم شود. پروتکل ارتباطی این ماژول از نوع I2C بوده و دارای سنسور دمای دیجیتال نیز می‌باشد.

در این پروژه هدف نحوه‌ی راه‌اندازی ماژول MPU6050 توسط رزبری پای و نمایش اطلاعات سنسور توسط نمایشگر کاراکتری 1602 می‌باشد.

مرحله 1 : اتصالات و دیاگرام مداری

معرفی پین‌های خروجی MPU6050

 • Vcc: ورودی تغذیه، 3.3V / 5V
• GND: منفی تغذیه 
• SDA: پین داده I2C
• SCL: پین کلاک I2C
• XDA و SDA: این دو پین زمانی استفاده می شود که از این ماژول به عنوان Master استفاده می‌شود.
• ADO: انتخاب آدرس ماژول به عنوان Slave 
• INT: وقفه خارجی (اختیاری)

دیاگرام مداری

در این پروژه ابتدا مقدار دمای خوانده‌شده توسط حسگر بر روی نمایشگر نشان داده می‌شود. سپس بعد از چند ثانیه مقدار سرعت زاویه‌ای و چند ثانیه بعد شتاب خطی در راستای سه محور نیز نشان داده خواهد شد.

دیاگرام مداری به این صورت است که یک پتانسیومتر 10k برای کنترل روشنایی LCD در نظر گرفته شده است.
برای تغذیه MPU6050 از3.3v و زمین رزبری پای بهره گرفته شده و پین‌های SCL و SDA ماژول باید به پین‌های 3 (GPIO2) و پین 5 (GPIO3) رزبری پای متصل شوند.
در مورد نمایشگر کاراکتری، پین‌های RS و EN به طور مستقیم به GPIO18 و GPIO23 متصل شده و پین‌های مربوط به دیتا به طور مستقیم به پین های GPIO24 ، GPIO25 ، GPIO8 و GPIO7 متصل می‌شوند.

 

مرحله 2 : فعال سازی پروتکل I2C رزبری پای

از آنجایی که پروتکل I2C به صورت پیش فرض بروی رزبری پای فعال نیست، لازم است قبل از نصب کتابخانه Adafruit SSD1306، این پروتکل ارتباطی را فعال کنیم.

گام اول : در ترمینال LXTerminal دستور زیر را تایپ و اجرا کنید.

sudo raspi-config

گام دوم : منویی جهت فعال سازی سرویس‌ها باز می‌شود. در قسمت Advanced Options گزینه‌ی هفتم که با نام I2C مشخص شده را انتخاب کنید.

گام سوم: گزینه‌ی Yes را که در هنگام انتخاب I2C رزبری مبنی بر تایید فعال سازی می‌پرسد ،انتخاب کنید.

گام چهارم: در این مرحله رزبری سوالی مبنی بر بار گذاری مجدد ماژول kernel خواهد پرسید، در پاسخ این سوال گزینه‌ی yes را انتخاب کنید.

گام پنجم: در آخر هم روی گزینه‌ی  Finish کلیک کرده و سیستم را ریبوت کنید. 

sodo reboot

 

مرحله 3 : نصب کتابخانه‌های python-pip و GPIO

sudo apt-get install build-essential python-dev python-pip

سپس کتابخانه GPIO را نصب می‌کنیم.

sudo pip installs RPi.GPIO

مرحله 4 : نصب کتابخانه smbus

در این مرحله باید با استفاده از دستور زیر، کتابخانه smbus را نصب کنید. وجود این کتابخانه باعث می‌شود که ارتباطات کارآمد و یکپارچه بین رزبری پای و برخی اجزای سخت‌افزاری فراهم شود. 

sudo apt-get install python-smbus

مرحله 5 : نصب کتابخانه MPU6050

در نهایت کتابخانه MPU6050 با استفاده از دستور زیر نصب می‌شود.

sudo pip install mpu6050


اکنون می توانیم کدهای نمونه را در مثال‌ها پیدا کنیم. کاربر می تواند  کد های نمونه را بر روی رزبری پای آپلود و تست کرده، یا طبق نیاز آن را تغییر دهد. در اینجا مقادیر دریافتی از ماژول را در راستای سه محور نشان داده‌ایم. 

مرحله 6 : کدنویسی و تنظیمات نرم‌افزاری

در برنامه پایتون برخی کتابخانه‌های مورد نیاز مانند زمان ، smbus و GPIO فراخوانی می‌شوند.

import smbus
import time
import RPi.GPIO as gpio

سپس برای پیکربندی و خواندن مقادیر MPU6050 آدرس رجیسترهای مورد نیاز را مشخص کرده وهمچنین متغیرهایی را برای کالیبراسیون وراه‌اندازی اولیه I2C در نظر می‌گیریم.

PWR_M   = 0x6B
DIV   = 0x19
CONFIG       = 0x1A
GYRO_CONFIG  = 0x1B
INT_EN   = 0x38
ACCEL_X = 0x3B
ACCEL_Y = 0x3D
ACCEL_Z = 0x3F
GYRO_X  = 0x43
GYRO_Y  = 0x45
GYRO_Z  = 0x47
TEMP = 0x41
bus = smbus.SMBus(1)

Device_Address = 0x68   # device address
AxCal=0
AyCal=0
AzCal=0
GxCal=0
GyCal=0
GzCal=0

 برخی از توابع  برای راه‌اندازی نمایشگر مانند begin(), def cmd(ch), def write(ch) def Print(str), def clear و... تعریف شده‌اند.

در این مرحله ماژول MPU6050 را راه‌اندازی اولیه می‌کنیم.

def InitMPU():
     bus.write_byte_data(Device_Address, DIV, 7)
     bus.write_byte_data(Device_Address, PWR_M, 1)
     bus.write_byte_data(Device_Address, CONFIG, 0)
     bus.write_byte_data(Device_Address, GYRO_CONFIG, 24)
     bus.write_byte_data(Device_Address, INT_EN, 1)
     time.sleep(1)

در این مرحله برخی از توابع را برای خواندن مقادیر از MPU6050 استفاده شده، سپس این مقادیر بر روی نمایشگر نشان داده می‌شوند. 

def accel():
     x = readMPU(ACCEL_X)
     y = readMPU(ACCEL_Y)
     z = readMPU(ACCEL_Z)
     Ax = (x/16384.0-AxCal)
     Ay = (y/16384.0-AyCal)
     Az = (z/16384.0-AzCal)
     #print "X="+str(Ax)
     display(Ax,Ay,Az)
     time.sleep(.01)
    
def gyro():
      global GxCal
      global GyCal
      global GzCal
      x = readMPU(GYRO_X)
      y = readMPU(GYRO_Y)
      z = readMPU(GYRO_Z)
      Gx = x/131.0 - GxCal
      Gy = y/131.0 - GyCal
      Gz = z/131.0 - GzCal
      #print "X="+str(Gx)
      display(Gx,Gy,Gz)
      time.sleep(.01)

سپس تابع زیر برای خواندن مقدار دما تعریف می‌شود.

def temp():
  tempRow=readMPU(TEMP)
  tempC=(tempRow / 340.0) + 36.53
  tempC="%.2f" %tempC
  print tempC
  setCursor(0,0)
  Print("Temp: ")
  Print(str(tempC))
  time.sleep(.2)

از تابع ()def calibrate برای کالیبراسیون MPU6050 استفاده می شود. همچنین تابع ()def display برای نمایش مقادیر بر روی نمایشگر استفاده می‌شود. این توابع را در کد کامل برنامه بررسی کنید. سپس LCD را فعال کرده ، MPI6050 را راه‌اندازی و کالیبراسیون و سپس در while، هر سه مجموعه مقادیر را ازاین ماژول فراخوانی کرده و در نهایت نمایش می‌دهیم.

begin();
Print("MPU6050 Interface")
setCursor(0,1)
Print("Circuit Digest")
time.sleep(2)
InitMPU()
calibrate()

while 1:
  InitMPU()
  clear()

  for i in range(20):
    temp()
  clear()
  Print("Accel")
  time.sleep(1)
  for i in range(30):
    accel()
  clear()
  Print("Gyro")
  time.sleep(1)
  for i in range(30):
  gyro()

کد کامل :

import smbus
import time
 
import RPi.GPIO as gpio
 
PWR_M   = 0x6B
DIV   = 0x19
CONFIG       = 0x1A
GYRO_CONFIG  = 0x1B
INT_EN   = 0x38
ACCEL_X = 0x3B
ACCEL_Y = 0x3D
ACCEL_Z = 0x3F
GYRO_X  = 0x43
GYRO_Y  = 0x45
GYRO_Z  = 0x47
TEMP = 0x41
bus = smbus.SMBus(1)
Device_Address = 0x68   # device address
 
AxCal=0
AyCal=0
AzCal=0
GxCal=0
GyCal=0
GzCal=0
 
 
RS =18
EN =23
D4 =24
D5 =25
D6 =8
D7 =7
 
gpio.setwarnings(False)
gpio.setmode(gpio.BCM)
gpio.setup(RS, gpio.OUT)
gpio.setup(EN, gpio.OUT)
gpio.setup(D4, gpio.OUT)
gpio.setup(D5, gpio.OUT)
gpio.setup(D6, gpio.OUT)
gpio.setup(D7, gpio.OUT)
 
 
def begin():
  cmd(0x33) 
  cmd(0x32) 
  cmd(0x06)
  cmd(0x0C) 
  cmd(0x28) 
  cmd(0x01) 
  time.sleep(0.0005)
 
def cmd(ch): 
  gpio.output(RS, 0)
  gpio.output(D4, 0)
  gpio.output(D5, 0)
  gpio.output(D6, 0)
  gpio.output(D7, 0)
  if ch&0x10==0x10:
    gpio.output(D4, 1)
  if ch&0x20==0x20:
    gpio.output(D5, 1)
  if ch&0x40==0x40:
    gpio.output(D6, 1)
  if ch&0x80==0x80:
    gpio.output(D7, 1)
  gpio.output(EN, 1)
  time.sleep(0.005)
  gpio.output(EN, 0)
  # Low bits
  gpio.output(D4, 0)
  gpio.output(D5, 0)
  gpio.output(D6, 0)
  gpio.output(D7, 0)
  if ch&0x01==0x01:
    gpio.output(D4, 1)
  if ch&0x02==0x02:
    gpio.output(D5, 1)
  if ch&0x04==0x04:
    gpio.output(D6, 1)
  if ch&0x08==0x08:
    gpio.output(D7, 1)
  gpio.output(EN, 1)
  time.sleep(0.005)
  gpio.output(EN, 0)
  
def write(ch): 
  gpio.output(RS, 1)
  gpio.output(D4, 0)
  gpio.output(D5, 0)
  gpio.output(D6, 0)
  gpio.output(D7, 0)
  if ch&0x10==0x10:
    gpio.output(D4, 1)
  if ch&0x20==0x20:
    gpio.output(D5, 1)
  if ch&0x40==0x40:
    gpio.output(D6, 1)
  if ch&0x80==0x80:
    gpio.output(D7, 1)
  gpio.output(EN, 1)
  time.sleep(0.005)
  gpio.output(EN, 0)
  # Low bits
  gpio.output(D4, 0)
  gpio.output(D5, 0)
  gpio.output(D6, 0)
  gpio.output(D7, 0)
  if ch&0x01==0x01:
    gpio.output(D4, 1)
  if ch&0x02==0x02:
    gpio.output(D5, 1)
  if ch&0x04==0x04:
    gpio.output(D6, 1)
  if ch&0x08==0x08:
    gpio.output(D7, 1)
  gpio.output(EN, 1)
  time.sleep(0.005)
  gpio.output(EN, 0)
def clear():
  cmd(0x01)
 
def Print(Str):
  l=0;
  l=len(Str)
  for i in range(l):
    write(ord(Str[i]))
    
def setCursor(x,y):
        if y == 0:
                n=128+x
        elif y == 1:
                n=192+x
        cmd(n)
 
 
def InitMPU():
bus.write_byte_data(Device_Address, DIV, 7)
bus.write_byte_data(Device_Address, PWR_M, 1)
bus.write_byte_data(Device_Address, CONFIG, 0)
bus.write_byte_data(Device_Address, GYRO_CONFIG, 24)
bus.write_byte_data(Device_Address, INT_EN, 1)
time.sleep(1)
 
def display(x,y,z):
      x=x*100
      y=y*100
      z=z*100
      x= "%d" %x
      y= "%d" %y
      z= "%d" %z
      setCursor(0,0)
      Print("X     Y     Z")
      setCursor(0,1)
      Print(str(x))
      Print("   ")
      setCursor(6,1)
      Print(str(y))
      Print("   ")
      setCursor(12,1)
      Print(str(z))
      Print("   ")
 
      print x
      print y
      print z
 
 
def readMPU(addr):
high = bus.read_byte_data(Device_Address, addr)
low = bus.read_byte_data(Device_Address, addr+1)
value = ((high << 8) | low)
if(value > 32768):
value = value - 65536
return value
def accel():
x = readMPU(ACCEL_X)
y = readMPU(ACCEL_Y)
z = readMPU(ACCEL_Z)
 
Ax = (x/16384.0-AxCal) 
Ay = (y/16384.0-AyCal) 
Az = (z/16384.0-AzCal)
 
#print "X="+str(Ax)
display(Ax,Ay,Az)
time.sleep(.01)
 
def gyro():
      global GxCal
      global GyCal
      global GzCal
      x = readMPU(GYRO_X)
      y = readMPU(GYRO_Y)
      z = readMPU(GYRO_Z)
      Gx = x/131.0 - GxCal
      Gy = y/131.0 - GyCal
      Gz = z/131.0 - GzCal
      #print "X="+str(Gx)
      display(Gx,Gy,Gz)
      time.sleep(.01)
 
def temp():
  tempRow=readMPU(TEMP)
  tempC=(tempRow / 340.0) + 36.53
  tempC="%.2f" %tempC
  print tempC
  setCursor(0,0)
  Print("Temp: ")
  Print(str(tempC))
  time.sleep(.2)
 
def calibrate():
  clear()
  Print("Calibrate....")
  global AxCal
  global AyCal
  global AzCal
  x=0
  y=0
  z=0
  for i in range(50):
      x = x + readMPU(ACCEL_X)
      y = y + readMPU(ACCEL_Y)
      z = z + readMPU(ACCEL_Z)
  x= x/50
  y= y/50
  z= z/50
  AxCal = x/16384.0
  AyCal = y/16384.0
  AzCal = z/16384.0
  
  print AxCal
  print AyCal
  print AzCal
 
  global GxCal
  global GyCal
  global GzCal
  x=0
  y=0
  z=0
  for i in range(50):
    x = x + readMPU(GYRO_X)
    y = y + readMPU(GYRO_Y)
    z = z + readMPU(GYRO_Z)
  x= x/50
  y= y/50
  z= z/50
  GxCal = x/131.0
  GyCal = y/131.0
  GzCal = z/131.0
 
  print GxCal
  print GyCal
  print GzCal
 
 
begin();
Print("MPU6050 Interface")
setCursor(0,1)
Print("Circuit Digest")
time.sleep(2)
InitMPU()
calibrate()
while 1:
  InitMPU()
  clear()
  for i in range(20):
    temp()
  clear()
  Print("Accel")
  time.sleep(1)
  for i in range(30):
    accel()
  clear()
  Print("Gyro")
  time.sleep(1)
  for i in range(30):
    gyro()