이 매뉴얼은 주식회사 제이케이이엠씨(JK EMC) 에 의해서 번역, 수정, 작성 되었고 소유권 또한
주 식회사 제이케이이엠씨(JK EMC)의 것입니다. 소유권자의 허가를 받지 않고 무단으로 수정, 삭제하거나 배포 할 수 없습니다.

 

 

ADXL335 3축 Accelerometer 가속도 GY-61 3.3/5V 레귤레이터 내장형 센서 메뉴얼


  * Update history

- 2016.8.3 : 프로세싱 코드 추가
- 2016.7.15 : 초기 Release


 
1. ADXL335 센서 소개
2. 아 두이노와 같이 사용하기
    2.1 센서 회로도및 외곽 치수
    2.2 아두이노 UNO R3 배선도
    2.3 아두이노 스케치 코드
3. 프로세싱을 이용해서 3차원 그래픽 표시
    3.1 프로세싱 설치 하기
    3.2 아두이노 UNO R3 배선도
    3.3 아두이노 스케치 코드
    3.4 프로세싱 코드



 

1. ADXL335 센서 소개

ADXL335는 3축(X, Y, Z)을 기준으로 회전각의 변화에 대한 가속도를 구할 수 있는데, 3축의 데이터를 아날로그 값으로 출력해준다.



Characteristic Value Unit
Supply Voltage 3.0 ~ 5.0 V
Supply Current 350 uA
Measuring range ±3.6 dps(deg/s)
Sensitivity(X/Y/Z) 270/300/330 mdps/digit
Measuring Axis X, Y, Z  
Operating Temperature -40 ~ 85 °C



2. 아두이노와 같이 사용하기

2.1 센서 회로도및 외곽 치수

(1) ADXL335 센서 회로도
     - ADXL335 PDF 회로도 다운로드
     - ADXL335 데이터시트 다운로드(http://www.jkelec.co.kr)
     - ADXL335 DXF 캐드 파일 다운로드

mpu9250

(2) ADXL335 센서 외곽(mm단위) 치수

      atmega128

2.2 아두이노 UNO R3 배선도

(1) 아두이노 UNO R3와 연결해서 가속도, 자이로 센터 데이터 출력 하기
      X축<->A0, Y축<->A1, Z축<->A2 와 연결한다. 본 제품은 내부에 회로적으로 3.3V전원 레듈레이터와 I2C 레벨쉬프터를 내장하고 있어서 5.0V와 3.3V 에서 모두 사용이 가능 하다. STM32, 라즈베리파이 등과 같이 3.3V 전원을 사용하는 프로세서에서 사용할 경우에는 VCC 대신에 3.3V 핀을 통해서 전원을 바로 연결해 주면 된다.


     - Fritzing 파일 다운로드

mpu9250

 



2.3 아두이노 스케치 코드

단순히 센서의 데이터를 시리얼 데이터로 출력하는 예제 이다.

(1) 아두이노 스케치 코드
     - ADXL335 raw 데이터 표시 스캐치 파일 다운로드

//////////////////////////////////////////////////////////////////
//©2011 bildr
//Released under the MIT License - Please reuse change and share
//Simple code for the ADXL335, prints calculated orientation via serial
//////////////////////////////////////////////////////////////////
//Analog read pins
const int xPin = 0;
const int yPin = 1;
const int zPin = 2;
//The minimum and maximum values that came from
//the accelerometer while standing still
//You very well may need to change these
int minVal = 265;
int maxVal = 402;
//to hold the caculated values
double x;
double y;
double z;
void setup(){
Serial.begin(9600); }
void loop(){
//read the analog values from the accelerometer
int xRead = analogRead(xPin);
int yRead = analogRead(yPin);
int zRead = analogRead(zPin);
//convert read values to degrees -90 to 90 - Needed for atan2
int xAng = map(xRead, minVal, maxVal, -90, 90);
int yAng = map(yRead, minVal, maxVal, -90, 90);
int zAng = map(zRead, minVal, maxVal, -90, 90);
//Caculate 360deg values like so: atan2(-yAng, -zAng)
//atan2 outputs the value of -π to π (radians)
//We are then converting the radians to degrees
x = RAD_TO_DEG * (atan2(-yAng, -zAng) + PI);
y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI);
z = RAD_TO_DEG * (atan2(-yAng, -xAng) + PI);
//Output the caculations
Serial.print("x: ");
Serial.print(x);
Serial.print(" | y: ");
Serial.print(y);
Serial.print(" | z: ");
Serial.println(z);
delay(100);//just here to slow down the serial output - Easier to read
}

(2) 실행 결과 

mpu9250

본 메뉴얼의 아두이노 코드는 아래 http://bildr.org/2011/04/sensing-orientation-with-the-adxl335-arduino/ 의 내용을 참조하여 작성 하였다.

3. 프로세싱을 이용해서 3차원 그래픽 표시

3.1 프로세싱 설치 하기

아두이노를 이용해서 센서에서 데이터를 추출해서 시리얼 데이터로 출력을 해서 데이터 값을 확인을 쉽게 할 수 있었다. 그렇다면 텍스트 데이터가 아니라 조금더 시각적인 표현 방법이 없을까? 그것도 아주 쉽게.. 
프로세싱을 이용하면 아두이노 스케치 코드를 입력하듯이 아주 쉽게 시각적인 표현이 가능하다. 우선 프로세싱 개발 환경을 설치하는것부터 해보자.

(1) 프로세싱 설치
      - 프로세싱 개발환경 설치 하기(새창)

3.2 아두이노 UNO R3 배선도

배선도는 이전 예제와 동일하다.

mpu6050

3.3 아두이노 스케치 코드

(1) 아두이노 프로세싱 코드
프로세싱 코드에서 한가지 주의 해야할 사항은 시리통 통신의 속도를 9600bps 로 설정을 하였다. 그렇기 때문에 아두이노의 시리얼 모니터창에서도 동일한 통신속도를 맞추어 주어야 한다.

     - ADXL335 아두이노, 프로세싱 스캐치 파일 다운로드


// Maurice Ribble 
// 6-28-2009
// http://www.glacialwanderer.com/hobbyrobotics
// This app just probes two external sensors (ADXL330 and IDG300) and
// then sends that data over a serial connection. I used a sparkfun
// breakout board to make using these chips easier.
// http://www.sparkfun.com/commerce/product_info.php?products_id=741
// I wrote a processing.org app that reads in this data and graphs it
// on a pc.
#define X_ACCEL_APIN 0
#define Y_ACCEL_APIN 1
#define Z_ACCEL_APIN 2
//#define V_REF_APIN 3
//#define Y_RATE_APIN 4
//#define X_RATE_APIN 5
void setup()
{
Serial.begin(115200);
}
// If this is defined it prints out the FPS that we can send a
// complete set of data over the serial port.
//#define CHECK_FPS
void loop()
{
int xAccel=0, yAccel=0, zAccel=0; // , vRef=0, xRate=0, yRate=0;
unsigned int startTag = 0xDEAD; // Analog port maxes at 1023 so this is a safe termination value
int loopCount;
#ifdef CHECK_FPS
unsigned long startTime, endTime;
startTime = millis();
#endif
// Can't do more than 64 loops or could overflow the 16 bit ints
// This just averages together as many sensor reads as we can in
// order to reduce sensor noise. Might want to introduce add
// a smarter filter her in the future.
loopCount = 12; // 12 gives a little over 100 FPS
for(int i = 0; i< loopCount; ++i)
{
// It takes 100 us (0.0001 s) to read an analog input
xAccel += analogRead(X_ACCEL_APIN);
yAccel += analogRead(Y_ACCEL_APIN);
zAccel += analogRead(Z_ACCEL_APIN);
//vRef += analogRead(V_REF_APIN);
//xRate += analogRead(X_RATE_APIN);
//yRate += analogRead(Y_RATE_APIN);
}
xAccel /= loopCount;
yAccel /= loopCount;
zAccel /= loopCount;
//vRef /= loopCount;
//xRate /= loopCount;
//yRate /= loopCount;
Serial.write( (unsigned byte*)&startTag, 2);
Serial.write((unsigned byte*)&xAccel, 2);
Serial.write((unsigned byte*)&yAccel, 2);
Serial.write((unsigned byte*)&zAccel, 2);
//Serial.write((unsigned byte*)&vRef, 2);
//Serial.write((unsigned byte*)&xRate, 2);
//Serial.write((unsigned byte*)&yRate, 2);
#ifdef CHECK_FPS
endTime = millis();
Serial.print(" - FPS: ");
Serial.println(1.f / (endTime-startTime) * 1000);
#endif
}

3.4 프로세싱 코드

프로세싱 코드에서 한가지 주의 해야할 사항은 시리얼 포트를 각자의 환경에 맞추어서 수정을 해주어야 한다는 것이다.
아래 프로세싱 코드에서 "[0]" 의 0이라는 숫자는 장치관리자에서 COM포트의 번호가 아니라 포트의 순서라는것에 주의 해야 한다.

mpu6050

위의 장치관리자 화면에서 예를 든다면 다음과 같다.

Serial.list()[0]; // --> COM31
Serial.list()[1]; // --> COM5

프로세싱 코드를 실행할때 테스트하는 PC의 COM 포트 상태에 따라서 "Serial.list()[0]" 의 숫자를 바꾸어 주어야 한다.

(1) 프로세싱 코드

// Maurice Ribble 
// 6-28-2009
// http://www.glacialwanderer.com/hobbyrobotics
// This takes data off the serial port and graphs it.
// There is an option to log this data to a file.
// I wrote an arduino app that sends data in the format expected by this app.
// The arduino app sends accelerometer and gyroscope data.
import processing.serial.*;
// Globals
int g_winW = 820; // Window Width
int g_winH = 600; // Window Height
// boolean g_dumpToFile = true; // Dumps data to c:\\output.txt in a comma seperated format (easy to import into Excel)
boolean g_enableFilter = true; // Enables simple filter to help smooth out data.
cDataArray g_xAccel = new cDataArray(200);
cDataArray g_yAccel = new cDataArray(200);
cDataArray g_zAccel = new cDataArray(200);
//cDataArray g_vRef = new cDataArray(200);
//cDataArray g_xRate = new cDataArray(200);
//cDataArray g_yRate = new cDataArray(200);
cGraph g_graph = new cGraph(10, 190, 800, 400);
Serial g_serial;
PFont g_font;
void setup()
{
size(820, 600, P2D);
println(Serial.list());
g_serial = new Serial(this, Serial.list()[0], 115200, 'N', 8, 1.0);
g_font = createFont("Arial",14,true);
fill(0, 0, 0);
}
void draw()
{
// We need to read in all the avilable data so graphing doesn't lag behind
while (g_serial.available() >= 2*6+2)
{
processSerialData();
}
strokeWeight(1);
fill(255, 255, 255);
g_graph.drawGraphBox();
strokeWeight(1.5);
stroke(255, 0, 0);
g_graph.drawLine(g_xAccel, 0, 1024);
stroke(0, 255, 0);
g_graph.drawLine(g_yAccel, 0, 1024);
stroke(0, 0, 255);
g_graph.drawLine(g_zAccel, 0, 1024);
// add axis info
// This draws the graph key info
strokeWeight(1.5);
stroke(255, 0, 0); line(20, 460, 40, 460);
stroke(0, 255, 0); line(20, 480, 40, 480);
stroke(0, 0, 255); line(20, 500, 40, 500); textFont(g_font,16); // STEP 3 Specify font to be used
fill(0); // STEP 4 Specify font color
text("xAccel", 60, 460);
text("yAccel", 60, 480);
text("zAccel", 60, 500);
/*
if (g_dumpToFile)
{
// This clears deletes the old file each time the app restarts
byte[] tmpChars = {'\r', '\n'};
saveBytes("c:\\output.txt", tmpChars);
}
*/ }
// This reads in one set of the data from the serial port
void processSerialData()
{
int inByte = 0;
int curMatchPos = 0;
int[] intBuf = new int[2];
intBuf[0] = 0xAD;
intBuf[1] = 0xDE;
while (g_serial.available() < 2); // Loop until we have enough bytes
inByte = g_serial.read();
// This while look looks for two bytes sent by the client 0xDEAD
// This allows us to resync the server and client if they ever
// loose sync. In my testing I haven't seen them loose sync so
// this could be removed if you need to, but it is a good way to
// prevent catastrophic failure.
while(curMatchPos < 2)
{
if (inByte == intBuf[curMatchPos])
{
++curMatchPos;
if (curMatchPos == 2)
break;
while (g_serial.available() < 2); // Loop until we have enough bytes
inByte = g_serial.read();
}
else
{
if (curMatchPos == 0)
{
while (g_serial.available() < 2); // Loop until we have enough bytes
inByte = g_serial.read();
}
else
{
curMatchPos = 0;
}
}
}
while (g_serial.available() < 2*3); // Loop until we have a full set of data
// This reads in one set of data
{
byte[] inBuf = new byte[2];
int xAccel, yAccel, zAccel, vRef, xRate, yRate;
g_serial.readBytes(inBuf);
// Had to do some type conversion since Java doesn't support unsigned bytes
xAccel = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
yAccel = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
zAccel = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
g_xAccel.addVal(xAccel);
g_yAccel.addVal(yAccel);
g_zAccel.addVal(zAccel);
/*
if (g_dumpToFile) // Dump data to a file if needed
{
String tempStr;
tempStr = xAccel + "," + yAccel + "," + zAccel + "," + vRef + "," + xRate + "," + yRate + "\r\n";
FileWriter file;
try
{
file = new FileWriter("c:\\output.txt", true); //bool tells to append
file.write(tempStr, 0, tempStr.length()); //(string, start char, end char)
file.close();
}
catch(Exception e)
{
println("Error: Can't open file!");
}
}
*/ /*
print(xAccel); print(" "); print(yAccel); print(" "); print(zAccel); print(" ");
print(vRef); print(" "); print(xRate); print(" "); println(yRate);
*/
}
}
// This class helps mangage the arrays of data I need to keep around for graphing.
class cDataArray
{
float[] m_data;
int m_maxSize;
int m_startIndex = 0;
int m_endIndex = 0;
int m_curSize;
cDataArray(int maxSize)
{
m_maxSize = maxSize;
m_data = new float[maxSize];
}
void addVal(float val)
{
if (g_enableFilter && (m_curSize != 0))
{
int indx;
if (m_endIndex == 0)
indx = m_maxSize-1;
else
indx = m_endIndex - 1;
m_data[m_endIndex] = getVal(indx)*.5 + val*.5;
}
else
{
m_data[m_endIndex] = val;
}
m_endIndex = (m_endIndex+1)%m_maxSize;
if (m_curSize == m_maxSize)
{
m_startIndex = (m_startIndex+1)%m_maxSize;
}
else
{
m_curSize++;
}
}
float getVal(int index)
{
return m_data[(m_startIndex+index)%m_maxSize];
}
int getCurSize()
{
return m_curSize;
}
int getMaxSize()
{
return m_maxSize;
}
}
// This class takes the data and helps graph it
class cGraph
{
float m_gWidth, m_gHeight;
float m_gLeft, m_gBottom, m_gRight, m_gTop;
cGraph(float x, float y, float w, float h)
{
m_gWidth = w;
m_gHeight = h;
m_gLeft = x;
m_gBottom = g_winH - y;
m_gRight = x + w;
m_gTop = g_winH - y - h;
}
void drawGraphBox()
{
stroke(0, 0, 0);
rectMode(CORNERS);
rect(m_gLeft, m_gBottom, m_gRight, m_gTop);
}
void drawLine(cDataArray data, float minRange, float maxRange)
{
float graphMultX = m_gWidth/data.getMaxSize();
float graphMultY = m_gHeight/(maxRange-minRange);
for(int i=0; i<data.getCurSize()-1; ++i)
{
float x0 = i*graphMultX+m_gLeft;
float y0 = m_gBottom-((data.getVal(i)-minRange)*graphMultY);
float x1 = (i+1)*graphMultX+m_gLeft;
float y1 = m_gBottom-((data.getVal(i+1)-minRange)*graphMultY);
line(x0, y0, x1, y1);
}
}
}

(2) 실행 결과



본 메뉴얼의 프로세싱 코드는 아래 URL의 내용을 참조하여 작성 하였다.
http://www.glacialwanderer.com/hobbyrobotics/?p=261

* 다른 센서들의 아두이노와 프로세싱 메뉴얼 보기

(1) MPU6050 GY-521 센서 아두이노, 프로세싱 메뉴얼(새창)
(2) MPU9250 GY-9250 센서 아두이노, 프로세싱 메뉴얼(새창)
(3) L3G4200D GY-50 센서 아두이노, 프로세싱 메뉴얼(새창)
(4) HMC5883L GY-271 센서 아두이노, 프로세싱 메뉴얼(새창)
(5) BMP180 GY-68 센서 아두이노, 프로세싱 메뉴얼(새창)
(6) ADXL345 GY-80 센서 아두이노, 프로세싱 메뉴얼(새창)
(7) ADXL335 GY-61 센서 아두이노, 프로세싱 메뉴얼(새창)