라즈베리 파이에서 MPU-6050 자이로 가속도 센서 모듈 제어하기

GY-521모듈은 MPU-6050 칩 기반으로 만들어진 가속도와 자이로 센서 모듈이다. 가속도와 각속도를 측정할 수 있다. 6축 – X, Y, Z축 자이로스코프 + 3축 – 가속도를 측정한다. 최근엔 주로 드론의 자세제어용으로 많이 사용한다고 한다. 나도 드론의 자세를 제어 할 수 있다는 말을 듣고 구입했다. 구입은 아래 링크에서 했고 가격은 1,600원이다. 무지 싸다.

https://www.devicemart.co.kr/goods/view?no=1247052

라즈베리파이와의 연결은 아래와 같다.

Pin No.1 –> VCC

Pin No.3 –> SDA

Pin No.5 –> SCL

Pin No.6 –> GND

라즈베리파이에서 이 모듈과 통신을 하기 위해서는 I2C 통신을 이용하는데 이게 뭔지는 (https://m.blog.naver.com/yuyyulee/220323559541) 여기서 보고 라즈베리파이에는 I2C통신을 위한 모듈을 설치하면 데이터를 받을 수 있다. 커맨드 라인에서 아래와 같이 설치한다.

> sudo apt-get install i2c-tools

제대로 연결이 되었는지는 아래의 커맨드로 확인 가능하다.

> sudo i2cdetect -y 1

위 그림과 같은 결과가 나타나면 제대로 연결된 것이다. 파이썬으로 이 모듈과 통신하려면 파이썬 라이브러리가 필요한데 아래와 같이 설치 할 수 있다

> sudo apt-get install python-smbus

데이터를 얻기 위해 사용한 코드는 아래와 같다. 대략 웹서핑해서 얻은 코드인데 문제없이 잘 작동 했다.

import smbus
import math

# Power management registers
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

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)



bus = smbus.SMBus(1) 
address = 0x68       

# Now wake the 6050 up as it starts in sleep mode

bus.write_byte_data(address, power_mgmt_1, 0)

while True:
    print "gyro data"
    print "---------"
    gyro_xout = read_word_2c(0x43)
    gyro_yout = read_word_2c(0x45)
    gyro_zout = read_word_2c(0x47)

    print "gyro_xout: ", gyro_xout, " scaled: ", (gyro_xout / 131)
    print "gyro_yout: ", gyro_yout, " scaled: ", (gyro_yout / 131)
    print "gyro_zout: ", gyro_zout, " scaled: ", (gyro_zout / 131)

    print
    print "accelerometer data"
    print "------------------"

    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
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0

    print "accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled
    print "accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled

    print "accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled
    print "x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)
    print "y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)

코드의 결과로 아래와 같은 화면을 연속적으로 얻을 수 있었다.

그런데 코드에서 상수로 표현된 131과 16384가 무었인지 궁금했다. 검색을 해보니 자이로센서, 가속센서 Scale Factor가 센싱범위가 +/- 250 degree/second, 2g일때 131, 16384 상수라고 한다. 무슨말인지 모르겠지만 이 값으로 나눠주면 된단다. 좀더 자세한 내용은 아래 링크 참조

https://github.com/FabLabSeoul/WingProject/wiki/Gyro-Accel-MPU-6050

GraphQL + MySQL 데이터 가져오기 스터디

네이버에 개발자 모집 공고를 보다가 React Native 개발자를 구하는데 GraphQL 기반의 백엔드 프로그래밍 역할도 필요하다는 것을 보고 놀랐다. 세상이 진짜 변하긴 했다.

물론 프론트 개발자가 백엔드를 동시에 작업할 수 있으면 매우 생산성이 높고 문서작업 & 협의 과정 없이 빠르게 서비스를 만들수 있다. 나는 Node.js 와 Vue.js를 이용해서 그런방식으로 작업을 하고 있는데 매번 프론트에서 엔드포인트가 필요할때마다 Node에서 api를 만들고 그걸 받아서 쓰고 있지만 프론트에서 이걸 끝내는 방법이 없나 하는 생각은 늘 하고 있던 차였다.

GraphQL이 이걸 해줄 수 있다고 해서 공부를 해봐야지 한게 벌써 두해를 넘기고 있기도 하고 여러가지 문서를 읽어 봤지만 역시 만들어 보는게 최고라… 그게 뭔지는 대충 아래 링크로 퉁치고 Hello World 와 좀 더 실제적인 Mysql DB에서 데이터를 읽어와서 뿌려주는데까지 한번 해보기로 했다.

Node.js & Express.js 로 서버를 구성하면 빠른방법으로 Hello World를 찍어 볼 수 있다.

> express --view=pug
> npm install express-graphql graphql

Express Generator를 이용해 프로젝트를 생성하고 npm으로 express-graphql, graphql을 설치했다.

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');

var app = express();

var schema = buildSchema(`
  type Query {
    hello: String
  }  
`);

var root = {
  hello: ()=>{
    return 'Hello World'
  },
};

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}));

코드를 실행하고 http://localhost:3000/graphql 에 접속하면 다음과 같은 화면을 볼 수 있다. 이것은 app.use() 에서 graphiql 옵션을 true로 셋팅하면 나타나는 화면으로 GraphQL의 테스트 인터페이스이다. 여기서 api를 미리 테스트 해볼 수 있다. 자동완성 기능도 지원한다.

Hello World는 찍었다. 대충 이제 다 알았다…는 아니고 현재 가장 많이 쓰고 있는 DB인 MySQL에 연결해서 데이터를 가져오는데 까지 해야한다. Node에서 MySQL 연결과 기타 과정은 생략하고 아래와 같은 코드를 작성 했다.

var app = express();
var schema = buildSchema(`
  type Query {
    user: [User]
  }
  
  type User {
    name: String
    age: Int
    sex: String
  }  
`);

var root = {
  user: ()=>{
    return new Promise(function (resolve) {
      pool.query('select * from users', function (err, res) {
        resolve(res);
      });
    });
  },
};

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}));

의의 코드를 실행한 결과로 아래와 같은 화면을 얻었다.

분명 데이터는 나왔는데 뭔가 잘못한게 아닌가 싶은 생각이 들었다. 타입도 서버에서 선언해 줘야 하고 쿼리도 서버에서 실행시킨다면 이게 기존의 REST API와 무었이 다른가? 그저 한개의 엔드 포인트를 쓴거 말고 다른게 있나 싶은 생각이 들었다.

그래서 좀 더 검색을 해봤다. 아래 링크에서 하나의 엔드포인트가 중요한 차이점이며 Query의 요청과정에서 파라메타의 차이로 결과를 다르게 가져올 수 있다는 점이 중요하다고 알려줬다.

https://www.holaxprogramming.com/2018/01/20/graphql-vs-restful-api/

결론

나는 이걸 어떻게 써야 하나 하는 문제가 고민이었는데 어차피 현재 Node.js 를 서버로 쓰고 있기 때문에 기존의 REST API에 GraphQL을 더 붙여 써도 괜찮지 않을까 하는 생각을 했다.

개발자들이 뭔가 바꾸고 싶으면 아주 갈아엎는(?) 나쁜 습성이 있지만 그러지 않아도 된다면 엔드 포인트 한두개씩 GraphQL로 바꿔도 무방할지 않을까 싶다.

소스코드는 아래 링크에 있습니다.

https://github.com/bipark/graphql_study

2020/12/10 박병일