본 체험 제품은 아이씨뱅큐(주)에서 진행하는 무상 체험단 활동으로 작성한 것입니다.


Tinker Board S의 GPIO활용과 관련하여 이전에 다음의 내용으로 포스팅 하였습니다.

- S/W 환경 설정, GPIO Digital I/O C/C++ 실험(http://alnova2.tistory.com/1225)

- GPIO DIgital I/O Python/Node.js 실험, PWM 실험(http://alnova2.tistory.com/1226)


이번 포스팅에서는 i2c 지원에 대해서 설명드리도록 하겠습니다.


1. I2C 센서 이용하기


[I2C 일반]

I2C는 Inter-Integrated Circuit의 약자로 버스 형태로 임베디드 시스템에서 저속의 주변기기를 연결하기 위해서 사용되는 프로토콜입니다.버스 형태여서 라인을 공유 가능하며 Address에 따라서 주변 장치와 통신이 가능합니다. SPI는 직렬연결인 것에 반하여 I2C는 병령연결이라고 할 수 있습니다.


Tinker Board S에서는 2개의 I2C를 지원한다고 되어 있습니다. gpio readall 명령으로 SDA/SCL을 찾아보면 3번핀(SDL1), 5번핀(SCL1) 및 27번핀(SDA4) 28번핀(SCL4)가 나옵니다.  Raspberry Pi 3B의 경우에도 gpio readall명령에는 3/5번핀(SDA.1/SCL.1) 과 27/28번(SDA.0/SCL.0)이 보입니다. 하지만 Raspberry Pi 3의 경우 i2c 0의 경우(27/28번핀) 다른 제어 용도로 사용하기 때문에 공식적으로는 지원이 안되며 공식적으로는 1개의 I2C만 지원하는 것으로 나와 있습니다.


i2c기본 툴을 Tinker Board에 설치해 보겠습니다. 다음의 명령으로 i2c tool을 설치합니다.


sudo apt-get install i2c-tools


다음의 명령으로 현재 연결된 i2c device 를 확인해 볼수 있습니다. 


sudo i2cdetect -y 0

sudo i2cdetect -y 1


아무것도 연결되어 있지 않은 경우 tinker board는 다음과 같은 출력을 보입니다.


Raspberry Pi의 경우 sudo i2cdetect -y 1에대해서는 정상 출력되지만 sudo i2cdetect -y 0을 하게 되면 다음과 같은 에러가 나타닙니다.

 

Tinker board S는 2개의 i2c를 지원하고, Raspberry Pi 3의 경우 SDA.1 1개의 i2c만을 지원하는 것으로 보여집니다.


[MPU6050 센서 연결]

이번 포스팅에서 i2c 주변장치는 MPU6050 센서로 실험을 해보겠습니다. MPU6050은 드론등에 들어가는 6축의 자이로+가속도 센서 입니다. 다음과 같이 3,5번핀의 I2C1번에 센서를 연결해 줍니다.



[C/C++ 프로그래밍]

Tinker Board S 와 Raspberry Pi 모두 wiringPi 라이브러리 기반으로  i2c 프로그래밍이 가능합니다. 다음은 MPU6050 센서 값을 읽어오는 C 코드입니다. (http://www.electronicwings.com/raspberry-pi/mpu6050-accelerometergyroscope-interfacing-with-raspberry-pi 참조함)


#include <wiringPiI2C.h>

#include <stdlib.h>

#include <stdio.h>

#include <wiringPi.h>


#define Device_Address 0x68 /*Device Address/Identifier for MPU6050*/


#define PWR_MGMT_1   0x6B

#define SMPLRT_DIV   0x19

#define CONFIG       0x1A

#define GYRO_CONFIG  0x1B

#define INT_ENABLE   0x38

#define ACCEL_XOUT_H 0x3B

#define ACCEL_YOUT_H 0x3D

#define ACCEL_ZOUT_H 0x3F

#define GYRO_XOUT_H  0x43

#define GYRO_YOUT_H  0x45

#define GYRO_ZOUT_H  0x47


int fd;

void MPU6050_Init(){

wiringPiI2CWriteReg8 (fd, SMPLRT_DIV, 0x07);

wiringPiI2CWriteReg8 (fd, PWR_MGMT_1, 0x01);

wiringPiI2CWriteReg8 (fd, CONFIG, 0);

wiringPiI2CWriteReg8 (fd, GYRO_CONFIG, 24);

wiringPiI2CWriteReg8 (fd, INT_ENABLE, 0x01);


short read_raw_data(int addr){

short high_byte,low_byte,value;

high_byte = wiringPiI2CReadReg8(fd, addr);

low_byte = wiringPiI2CReadReg8(fd, addr+1);

value = (high_byte << 8) | low_byte;

return value;

}


int main(){

float Acc_x,Acc_y,Acc_z;

float Gyro_x,Gyro_y,Gyro_z;

float Ax=0, Ay=0, Az=0;

float Gx=0, Gy=0, Gz=0;

fd = wiringPiI2CSetup(Device_Address);   /*Initializes I2C with device Address*/

MPU6050_Init();                  /* Initializes MPU6050 */

while(1)

{

/*Read raw value of Accelerometer and gyroscope from MPU6050*/

Acc_x = read_raw_data(ACCEL_XOUT_H);

Acc_y = read_raw_data(ACCEL_YOUT_H);

Acc_z = read_raw_data(ACCEL_ZOUT_H);

Gyro_x = read_raw_data(GYRO_XOUT_H);

Gyro_y = read_raw_data(GYRO_YOUT_H);

Gyro_z = read_raw_data(GYRO_ZOUT_H);

/* Divide raw value by sensitivity scale factor */

Ax = Acc_x/16384.0;

Ay = Acc_y/16384.0;

Az = Acc_z/16384.0;

Gx = Gyro_x/131;

Gy = Gyro_y/131;

Gz = Gyro_z/131;

printf("\n Gx=%.3f °/s\tGy=%.3f °/s\tGz=%.3f °/s\tAx=%.3f g\tAy=%.3f g\tAz=%.3f g\n",Gx,Gy,Gz,Ax,Ay,Az);

delay(100);

}

return 0;

}

 


 gcc -o mpu6050 ./mpu6050.c -lwiringPi 로 컴파일 하고 실행하면 다음과 같이 센서 값이 화면에 출력됩니다. (Raspberry Pi 도 동일하게 동작합니다.)


[Python 프로그래밍]

Python에서 i2c 버스를 이용하기 위해서는 python-smbus 라는 패키지가 필요합니다. Raspberry Pi에서는 기본적으로 설치되어 있습니다. Tinker Board에서는 다음과 같이 python-smbus 패키지를 설치 합니다.


$sudo apt-get install python-smbus


다음은 mpu6050센서에서 값을 읽어서 출력하는 프로그램입니다. (http://blog.bitify.co.uk/2013/11/reading-data-from-mpu-6050-on-raspberry.html 의 코드를 변형하였습니다.)

#!/usr/bin/python


import smbus

import math

import time


# 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) # or bus = smbus.SMBus(1) for Revision 2 boards

address = 0x68       # This is the address value read via the i2cdetect command


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

bus.write_byte_data(address, power_mgmt_1, 0)


def print_mpu6050():

    gyro_xout = read_word_2c(0x43)

    gyro_yout = read_word_2c(0x45)

    gyro_zout = read_word_2c(0x47) 

    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 "gx:",gyro_xout," gy:",gyro_yout," gz:",gyro_zout

    print " ax:",accel_xout," ay:",accel_yout," zy:",accel_zout

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


while True:

    print_mpu6050()

    time.sleep(0.1) 


이 코드는 Raspberry Pi, TInker Board S 모두 동작합니다. 다음은 출력 화면입니다.


[비교 후기]

i2c관련해서 C/C++, Python 사용에 큰 문제는 없어 보입닏다. wiringPi 라이브러리 기반의 프로그램 및 python-smbus기반 프로그램 모두 Tinker Board S와 Raspberry Pi에서 소스 수정 없이 잘 동작함을 확인해 볼수 있습니다.


[리뷰 총평]

Tinker Board S의 GPIO는 wiringPi 기반으로 제공되어 Digital I/O, PWM, I2C 등 활용에는 큰 문제가 없어 보입니다. 기본적으로 C/C++, Python 등의 환경에서 활용이 가능합니다. Raspberry Pi의 GPIO를 이용하는 C/C++, Python Code가 거의 수정 없이 빌드-실행이 가능합니다. SPI의 경우 관련 센서가 없어서 확인은 못해보았습니다만, I2C와 유사할 것으로 생각됩니다. 

다만 tinker board s의 경우 C, Python 이외의 프로그래밍 언어의 GPIO 이용은 사실상 지원이 안된다고 봐야 할듯 합니다. 이건 보드 자체의 문제라기 보다는 커뮤니티가 활성화 되지 않아서 그렇습니다. 예를 들어, Raspberry Pi의 node.js의 경우에는 커뮤니티에서  wiringPi 나 bcm2835 library를 가지고 지원하는 패키지들을 만들었기 때문에 사용할수 있는 패키지들이 있는 것이지요. Tinker Board S도 사용층이 두터워 지면 조금식 라이브러리도 풍부해 질 것으로 생각 됩니다.


이상 GPIO 이용 및 Raspberry Pi와의 비교 포스팅을 마치겠습니다.


다음은 GPIO 관련 포스팅입니다. 

1. 개발 환경 및 Digital I/O(C/C++) 설명/RPI 비교: http://alnova2.tistory.com/1225

2. Digital I/O 설명(Python/Node.js) 및 PWM 설명/RPI비교 : http://alnova2.tistory.com/1226

3. i2c 설명 및 총평/RPI 비교: http://alnova2.tistory.com/1227



- ASUS 팅커보드 S 공식 구입처: 아이씨뱅큐 http://www.icbanq.com/

- 아이씨뱅큐 공식 카페: http://cafe.naver.com/icbanq

- 아이씨뱅큐 공식 블로그: http://blog.naver.com/icbanq










Posted by alias