Датчик MPU6050 способен выполнять несколько функций и содержит в своем составе акселерометр, гироскоп и датчик температуры. Он находит широкое применение при конструировании дронов, роботов и многих других устройств. Иногда его называют гироскопом или трехосевым акселерометром.
Данный датчик также обеспечивает превосходную точность результатов благодаря наличию в нем 16-битного АЦП (аналого-цифрового преобразования). Гироскоп датчика MPU6050 способен одновременно обрабатывать данные по 3-м осям: x, y и z. Для связи с другими устройствами датчик использует интерфейс I2C.
В данной статье мы рассмотрим подключение гироскопа MPU6050 к плате Raspberry Pi, получаемые данные с гироскопа мы будем выводить на экран ЖК дисплея 16x2.
Также на нашем сайте вы можете посмотреть следующие проекты, в которых был использован датчик MPU6050:
- подключение гироскопа MPU6050 к плате Arduino;
- измеритель уровня на основе Arduino и MPU6050;
- самобалансирующийся робот на Arduino Uno;
- управляемая жестами роботизированная рука на Arduino.
Необходимые компоненты
- Плата Raspberry Pi (купить на AliExpress).
- ЖК дисплей 16x2 (купить на AliExpress).
- Гироскоп MPU6050 (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- Источник питания.
- Макетная плата.
- Соединительные провода.
Гироскопический датчик (гироскоп) MPU-6050
MPU-6050 представляет собой 8-пиновый 6-осевой гироскоп и акселерометр на едином чипе. По умолчанию данный модуль работает по интерфейсу I2C, но можно задействовать и интерфейс SPI. В нашем проекте мы будем использовать интерфейс (режим) I2C и в этом режиме нам понадобятся контакты SDA и SCL модуля.
Распиновка MPU-6050:
Vcc – контакт для подачи питающего напряжения постоянного тока;
GND – земля модуля;
SDA – это контакт используется для передачи данных между модулем mpu6050 и микроконтроллером;
SCL – вход синхронизации;
XDA – линия передачи данных (опциональная) по протоколу I2C для конфигурирования и считывания данных с внешних датчиков (не используется в нашем проекте);
XCL – вход синхронизации протокола I2C для конфигурирования и считывания данных с внешних датчиков (не используется в нашем проекте);
ADO – I2C Slave Address LSB (не используется в нашем проекте);
INT – контакт прерывания для индикации готовности данных.
Общие принципы работы проекта
В этом проекте мы будем с помощью платы Raspberry Pi считывать с датчика MPU6050 данные температуры, гироскопа и акселерометра и последовательно отображать их на экране ЖК дисплея: сначала температуру, затем после небольшой паузы данные гироскопа и затем данные акселерометра.
Схема проекта
Схема подключения гироскопа MPU6050 к плате Raspberry Pi представлена на следующем рисунке.
Потенциометр 10 кОм в схеме используется для регулировки контрастности ЖК дисплея. Для соединения платы Raspberry Pi с датчиком MPU6050 мы использовали 4 провода: 3.3v и землю датчика MPU6050 подключили к 3.3v и земле платы Raspberry Pi, а контакты SCL и SDA датчика подключили к контактам 3 (GPIO2) и 5 (GPIO3) платы. Контакты управления работой ЖК дисплея RS, RW и EN мы непосредственно подключили к контактам GPIO18 и 23 платы Raspberry Pi, а контакты данных ЖК дисплея мы подключили к контактам GPIO24, GPIO25, GPIO8 и GPIO7 платы.
Настройка платы Raspberry Pi для работы с датчиком MPU6050
Выполните следующую последовательность шагов.
Шаг 1. Активируйте интерфейс I2C в плате Raspberry Pi.
Для этого сначала войдите в настройки платы:
1 |
sudo raspi-config |
В открывшемся окне настроек выберите настройки подключения периферийных устройств.
Затем выберите I2C.
После этого нажмите yes, затем enter и затем ok.
После этого перезагрузите плату Raspberry Pi чтобы настройки вступили в силу.
1 |
sudo reboot |
Шаг 2. Установите python-pip и GPIO Library (библиотеку для работы с контактами).
Для установки pip выполните следующую команду:
1 |
sudo apt-get install build-essential python-dev python-pip |
После этого установим библиотеку для работы с контактами (GPIO library).
1 |
sudo pip installs RPi.GPIO |
Шаг 3. Установите библиотеку smbus.
Библиотеку smbus можно установить с помощью следующей команды:
1 |
sudo apt-get install python-smbus |
Шаг 4. Установите библиотеку для работы с датчиком MPU6050.
Данную библиотеку можно установить с помощью следующей команды:
1 |
sudo pip install mpu6050 |
Объяснение программы для Raspberry Pi
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Первым делом в программе нам необходимо подключить (импортировать) используемые библиотеки.
1 2 3 4 |
import smbus import time import RPi.GPIO as gpio |
Далее нам необходимо задать начальные значения регистров для настройки датчика MPU6050. Также инициализируем ряд переменных и шину для работы протокола I2C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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 |
Далее запрограммируем ряд функций для работы с ЖК дисплеем: def begin(), def cmd(ch), def write(ch), def Print(str), def clear(). Их коды представлены в полном тексте программы в конце статьи. Более подробно о назначении этих функций вы можете прочитать в статье про управление светодиодами по радиоканалу с помощью Raspberry Pi.
После этого запрограммируем функцию для инициализации датчика MPU6050.
1 2 3 4 5 6 7 |
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.
1 2 3 4 5 6 7 |
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 |
Следующие две функции будут использоваться для считывания данных акселерометра и гироскопа с датчика MPU6050.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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) |
Затем запрограммируем функцию для считывания значения температуры с датчика.
1 2 3 4 5 6 7 8 9 |
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() для отображения информации на экране ЖК дисплея.
Затем в основном цикле программы мы будем вызывать ранее запрограммированные функции для инициализации и калибровки датчика MPU6050, после чего последовательно считывать с него значения температуры, акселерометра и гироскопа и отображать их на экране ЖК дисплея.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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() |
В данной статье мы рассмотрели основы работы с гироскопом с помощью платы Raspberry Pi, на ее основе вы сможете создать свои более сложные проекты с использованием гироскопа.
Исходный код программы на Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
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() |