공부시간: 1시간 30분
밸런싱 로봇 만들기
1. ESP8266을 이용하여 스탭모터 움직이기
2. ESP8266을 이용하여 중력센서 데이터 받기
3. ESP8266을 이용하여 PID 모터제어하기
GY-521 MPU6050
MPU6050은 3축 중력센서와 3축 가속도 센서와 온도센서가 달린 모듈이다. I2C 통신을 이용하여 MCU과 연결할 수 있다.
ESP8266에는 물리적 SDA와 SCL이 없기 때문에 핀번호를 직접 지정하여 I2C통신을 할 수 있다. 2)
MPU6050에서 데이터 확인하기 위해서 다음과 같은 코드를 사용하였다. Wire.h 라이브러리를 이용해서 ESP8266과 MPU6050간 데이터를 I2C를 주고 받는다. ESP8266이 사용하는 115200 baudrate 로 설정하고 wire.begin(4,5) 을 이용하여 SDA, SCL 을 지정하였다. 5) 2)
#https://mschoeffler.com/2017/10/05/tutorial-how-to-use-the-gy-521-module-mpu-6050-breakout-board-with-the-arduino-uno/
// (c) Michael Schoeffler 2017, http://www.mschoeffler.de
#include "Wire.h" // This library allows you to communicate with I2C devices.
const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.
int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data
char tmp_str[7]; // temporary variable used in convert function
char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
sprintf(tmp_str, "%6d", i);
return tmp_str;
}
void setup() {
Serial.begin(115200);
Wire.begin(4,5);
Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
}
void loop() {
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers
// "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
// print out data
Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
// the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
Serial.print(" | tmp = "); Serial.print(temperature/340.00+36.53);
Serial.print(" | gX = "); Serial.print(convert_int16_to_str(gyro_x));
Serial.print(" | gY = "); Serial.print(convert_int16_to_str(gyro_y));
Serial.print(" | gZ = "); Serial.print(convert_int16_to_str(gyro_z));
Serial.println();
// delay
delay(1000);
}
발생했던 오류들
처음에 SDA와 SCL에 연결하고 코드를 실행하였더니 각 센서의 값이 -1 로 나오고 아무런 변화가 없었다. 아무런 변화가 없다는 것은 무언가 연결되지 않았다는 것이여서 선을 바꿔서 연결해 보았지만 고칠 수 없었다. 처음에는 SDA와 SCL의 핀을 잘못 연결할 것 같아서 이것 저것 바꿔봤지만 해결되지 않았다.
I2C의 통신이 잘되는지 I2C 스캐너를 이용하여 테스트해보았다. 센서값이 -1이 나오는 상태에서는 I2C 주소를 검색할 수 없다고 스캔되었다. 그래서 SDA와 SCL 핀의 위치를 다시 지정하여 테스트해보니 주소가 정상적으로 나왔다. (I0x68, MPU-6050의 I2C 주소)
I2C 스캐너코드
// Arduino I2C Scanner
// Re-writed by Arbi Abdul Jabbaar
// Using Arduino IDE 1.8.7
// Using GY-87 module for the target
// Tested on 10 September 2019
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
#include <Wire.h> //include Wire.h library
void setup()
{
Wire.begin(4,5); // Wire communication begin
Serial.begin(115200); // The baudrate of Serial monitor is set in 9600
while (!Serial); // Waiting for Serial Monitor
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address; //variable for error and I2C address
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for (address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address < 16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
}
else if (error == 4)
{
Serial.print("Unknown error at address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for the next I2C scan
}
해야할것
1. 각 코드가 어떤것을 의미하는지 알아보기
2. raw data를 교정(calibration) 하기
3. 가속도센서를 이용하여 PID 컨트롤 하는 방법에 대해서 공부하기
참고
1)https://www.hotmcu.com/gy521-mpu6050-3axis-acceleration-gyroscope-6dof-module-p-83.html
2)
https://learn.sparkfun.com/tutorials/esp8266-thing-hookup-guide/using-the-arduino-addon
3)
https://create.arduino.cc/projecthub/abdularbi17/how-to-scan-i2c-address-in-arduino-eaadda
4)
https://www.youtube.com/watch?v=wTfSfhjhAU0&ab_channel=MichaelSchoeffler
'만들기 > 아두이노' 카테고리의 다른 글
아두이노 DC모터 움직이기( 건전지 전류용량 차이) (0) | 2021.06.26 |
---|---|
[밸런싱로봇] PID 제어 이해하기 (1) (0) | 2021.06.25 |
esp 8266에서 DHT 온습도센서 2147483647 혹은 nan 오류 (0) | 2021.06.25 |
MPU 6050 센서값 보정하기 ( 90% 이해) (1) | 2021.06.22 |
[로봇] GY-521 MPU6050 I2C 통신 이해하기 (0) | 2021.06.21 |