Датчик MPU6050 состоит из акселерометра и гироскопа, объединенных в составе одного чипа. Он содержит 16-битный аналого-цифровой преобразователь (АЦП) на каждый канал. Таким образом, он одновременно может считывать показания по всем осям x, y и z. Для взаимодействия с платами Arduino или другими микроконтроллерами модуль использует интерфейс I2C. Модуль MPU-6050 находит широкое применение в дронах, роботах, датчиках движения и т.д.
В данной статье мы рассмотрим подключение гироскопа и акселерометра MPU6050 к модулю ESP32 и будем выводить считываемые с него значения на веб-сервер. Ранее на нашем сайте мы рассматривали подключение гироскопа MPU6050 к платам Arduino и Raspberry Pi. Также у нас на сайте вы можете посмотреть все проекты с использованием модуля MPU6050.
Необходимые компоненты
- ESP32 NodeMCU (купить на AliExpress).
- Модуль акселерометра и гироскопа MPU6050 (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Гироскопический датчик (гироскоп) 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 – контакт прерывания для индикации готовности данных.
Схема проекта
Схема подключения гироскопа MPU6050 к модулю ESP32 представлена на следующем рисунке.
Модуль MPU6050 взаимодействует с ESP32 по интерфейсу I2C, поэтому нам необходимо всего два провода для его подключения. Контакты SCL и SDA модуля MPU6050 мы подключим к контактам D22 и D21 модуля ESP32, а контакты VCC и GND модуля MPU6050 подсоединим к контактам 3.3V и GND модуля ESP32.
Объяснение программы для модуля ESP32
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Первым делом в программе мы подключим используемые библиотеки. Библиотека Wire.h позволяет взаимодействовать с I2C/TWI устройствами, а библиотека WiFi.h позволяет модулю ESP32 подключаться к сетям Wi-Fi.
1 2 |
#include <Wire.h> #include <WiFi.h> |
Далее объявим используемые переменные для хранения данных гироскопа и акселерометра.
1 |
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; |
Затем укажем данные для доступа к сети Wi-Fi – имя сети и пароль.
1 2 |
const char *ssid = "Galaxy-M20"; // Enter your Wi-Fi Name const char *pass = "ac312124"; // Enter your Wi-Fi Password |
Внутри функции void setup() мы инициализируем последовательную связь со скоростью 115200 бод, библиотеку wire, веб-сервер и передачу данных через регистр управления мощностью.
1 2 3 4 5 6 |
Serial.begin(115200); Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(0x6B); Wire.write(0); server.begin(); |
Внутри функции void loop() мы будем вызывать функцию mpu_read для считывания данных акселерометра и гироскопа. Далее мы будем передавать эти данные на веб-страницу с помощью функции client.println().
1 |
mpu_read(); |
В следующих строках кода мы будем проверять передал ли клиент HTTP запрос или нет. Если модуль ESP32 получил какой-нибудь клиентский запрос, то мы будем сохранять его в символьной переменной и выводить в окно монитора последовательной связи.
1 2 3 4 5 6 7 8 9 10 11 |
WiFiClient client = server.available(); if (client) { Serial.println("new client"); String currentLine = ""; while (client.connected()) { if (client.available()) { char c = client.read(); if (c == '\n') |
Далее запрограммируем дизайн нашей веб-страницы с помощью html кодов и передадим каждую строку с этими кодами на веб-страницу с помощью функции client.println(). Тэг <style> используется для изменения цвета текста и фона. Вы можете изменить дизайн данной веб-страницы по своему желанию.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
client.print("<html><title> ESP32 WebServer</title></html>"); client.print("<body bgcolor=\"#E6E6FA\"><h1 style=\"text-align: center; color: blue\"> ESP32 WebServer </h1>"); client.print("<p style=\"text-align: left; color: red; font-size:150% \">Accelerometer Values: "); client.print("<p style=\"text-align: left; font-size:150% \">AcX: "); client.print(AcX); client.print("<br/>AcY: "); client.print(AcY); client.print("<br/>AcZ: "); client.print(AcZ); client.print("<p style=\"text-align: left; color: red; font-size:150% \">Gyroscope Values: "); client.print("<p style=\"text-align: left; font-size:150% \">GyX: "); client.print(GyX); client.print("<br/>GyY: "); client.print(GyY); client.print("<br/>GyZ: "); client.print(GyZ); client.print("</p></body>"); |
Внутри функции mpu_read мы будем считывать значения всех 6 регистров для осей X, Y и Z акселерометра и гироскопа.
1 2 3 4 5 6 |
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) |
Тестирование работы проекта
Подключите модуль ESP32 к компьютеру/ноутбуку и загрузите в него код программы. Не забудьте в Arduino IDE выбрать правильный тип платы и COM порт, к которому подключен модуль.
Убедитесь в том, что ваш компьютер/ноутбук и модуль ESP32 подключены к одной и той же сети Wi-Fi. После загрузки кода программы в модуль откройте окно монитора последовательной связи – измените в нем скорость на 115200. В окне монитора последовательной связи вы увидите IP адрес модуля ESP32 и данные гироскопа и акселерометра. Скопируйте этот IP адрес и вставьте его в адресную строку браузера. После этого вы увидите веб-страницу, на которой будут отображаться данные, считываемые с акселерометра и гироскопа 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 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 |
#include <Wire.h> #include <WiFi.h> const int MPU_addr=0x68; // I2C адрес модуля MPU-6050 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; // WiFi network info. const char *ssid = "Galaxy-M20"; // Enter your WiFi Name const char *pass = "ac312124"; // Enter your WiFi Password WiFiServer server(80); void setup(){ Serial.begin(115200); Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // устанавливаем в 0 (это "пробуждает" модуль MPU-6050) Wire.endTransmission(true); Serial.println("Wrote to IMU"); Serial.println("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); // печатаем ... пока не подключимся к сети WiFi } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address is : "); Serial.println(WiFi.localIP()); server.begin(); Serial.println("Server started"); } void loop(){ mpu_read(); WiFiClient client = server.available(); if (client) { Serial.println("new client"); String currentLine = ""; //сохраняем поступающие данные в строке while (client.connected()) { if (client.available()) //если от клиента поступают какие либо данные { char c = client.read(); // считываем байт if (c == '\n') // проверяем на символ перевода строки { if (currentLine.length() == 0) //if line is blank it means its the end of the client HTTP request (конец HTTP запроса) { client.print("<html><title> ESP32 WebServer</title></html>"); client.print("<body bgcolor=\"#E6E6FA\"><h1 style=\"text-align: center; color: blue\"> ESP32 WebServer </h1>"); client.print("<p style=\"text-align: left; color: red; font-size:150% \">Accelerometer Values: "); client.print("<p style=\"text-align: left; font-size:150% \">AcX: "); client.print(AcX); client.print("<br/>AcY: "); client.print(AcY); client.print("<br/>AcZ: "); client.print(AcZ); client.print("<p style=\"text-align: left; color: red; font-size:150% \">Gyroscope Values: "); client.print("<p style=\"text-align: left; font-size:150% \">GyX: "); client.print(GyX); client.print("<br/>GyY: "); client.print(GyY); client.print("<br/>GyZ: "); client.print(GyZ); client.print("</p></body>"); break; // break out of the while loop: } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // добавляем этот символ в конец текущей строки } } } } } void mpu_read(){ Wire.beginTransmission(MPU_addr); Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) //Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) Serial.print("Accelerometer Values: \n"); Serial.print("AcX: "); Serial.print(AcX); Serial.print("\nAcY: "); Serial.print(AcY); Serial.print("\nAcZ: "); Serial.print(AcZ); //Serial.print("\nTemperature: " ); Serial.print(Tmp); Serial.print("\nGyroscope Values: \n"); Serial.print("GyX: "); Serial.print(GyX); Serial.print("\nGyY: "); Serial.print(GyY); Serial.print("\nGyZ: "); Serial.print(GyZ); Serial.print("\n"); delay(3000); } |
Что-то мне подсказывает, что MPU не в курсе, что Вы закомментировали 88 строку и в переменной GyX будет лежать температура, а в GyY - значение гироскопа по X, в GyZ...
...ну Вы поняли логику =)
Ну, возможно,вы правы, логику я понял, но проверить пока возможности нет поскольку нахожусь сейчас в отъезде в отпуске