ÀÌ ¸Å´º¾óÀº ÁÖ½Äȸ»ç Á¦ÀÌÄÉÀÌÀÌ¿¥¾¾(JK EMC) ¿¡ ÀÇÇؼ­ ¹ø¿ª, ¼öÁ¤, ÀÛ¼º µÇ¾ú°í ¼ÒÀ¯±Ç ¶ÇÇÑ
ÁÖ ½Äȸ»ç Á¦ÀÌÄÉÀÌÀÌ¿¥¾¾(JK EMC)ÀÇ °ÍÀÔ´Ï´Ù. ¼ÒÀ¯±ÇÀÚÀÇ Çã°¡¸¦ ¹ÞÁö ¾Ê°í ¹«´ÜÀ¸·Î ¼öÁ¤, »èÁ¦Çϰųª ¹èÆ÷ ÇÒ ¼ö ¾ø½À´Ï´Ù.

 

 

ADXL345 3Ãà Accelerometer °¡¼Óµµ GY-80 3.3/5V ·¹±Ö·¹ÀÌÅÍ ³»ÀåÇü ¼¾¼­ ¸Þ´º¾ó


  * Update history

- 2016.8.3 : ÇÁ·Î¼¼½Ì ÄÚµå Ãß°¡
- 2016.7.15 : Ãʱâ Release


 
1. ADXL345 ¼¾¼­ ¼Ò°³
2. ¾Æ µÎÀ̳ë¿Í °°ÀÌ »ç¿ëÇϱâ
    2.1 ¼¾¼­ ȸ·Îµµ¹× ¿Ü°û Ä¡¼ö
    2.2 ¾ÆµÎÀ̳ë UNO R3 ¹è¼±µµ
    2.3 ¾ÆµÎÀÌ³ë ½ºÄÉÄ¡ ÄÚµå
3. ÇÁ·Î¼¼½ÌÀ» ÀÌ¿ëÇؼ­ 3Â÷¿ø ±×·¡ÇÈ Ç¥½Ã
    3.1 ÇÁ·Î¼¼½Ì ¼³Ä¡ Çϱâ
    3.2 ¾ÆµÎÀ̳ë UNO R3 ¹è¼±µµ
    3.3 ¾ÆµÎÀÌ³ë ½ºÄÉÄ¡ ÄÚµå
    3.4 ÇÁ·Î¼¼½Ì ÄÚµå



 

1. ADXL345 ¼¾¼­ ¼Ò°³

SPI¿Í I2C ÀÎÅÍÆäÀ̽º¸¦ Áö¿øÇÏ´Â ¾Æ³¯·Î±× µð¹ÙÀ̽º»çÀÇ ÀúÀü·Â µðÁöÅÐ 3Ãà °¡¼Óµµ ¼¾¼­ ÀÌ´Ù. ¾Æ³¯·Î±× Ãâ·ÂÀÌ ³ª¿À´Â ADXL335¼¾¼­º¸´Ù ºñ±³Àû ½±°Ô »ç¿ëÀÌ °¡´ÉÇÏ´Ù.


Characteristic Value Unit
Supply Voltage 2.0 ~ 3.6 V
Supply Current 140 uA
Measuring range(Selectable) ¡¾2, ¡¾4, ¡¾8, ¡¾16 dps(deg/s)
Sensitivity FPS = ¡¾2g 256 LSB/g
FPS = ¡¾4g 128
FPS = ¡¾6g 64
FPS = ¡¾8g 30
Measuring Axis X, Y, Z  
Operating Temperature -40 ~ 85 ¡ÆC



2. ¾ÆµÎÀ̳ë¿Í °°ÀÌ »ç¿ëÇϱâ

2.1 ¼¾¼­ ȸ·Îµµ¹× ¿Ü°û Ä¡¼ö

(1) ADXL345 ¼¾¼­ ȸ·Îµµ
     - ADXL345 PDF ȸ·Îµµ ´Ù¿î·Îµå
     - ADXL345 µ¥ÀÌÅͽÃÆ® ´Ù¿î·Îµå(http://www.jkelec.co.kr)
     - ADXL345 DXF ijµå ÆÄÀÏ ´Ù¿î·Îµå

mpu9250

(2) ADXL345 ¼¾¼­ ¿Ü°û(mm´ÜÀ§) Ä¡¼ö

      atmega128

2.2 ¾ÆµÎÀ̳ë UNO R3 ¹è¼±µµ

(1) ¾ÆµÎÀ̳ë UNO R3¿Í ¿¬°áÇؼ­ °¡¼Óµµ, ÀÚÀÌ·Î ¼¾ÅÍ µ¥ÀÌÅÍ Ãâ·Â Çϱâ
º» Á¦Ç°Àº ³»ºÎ¿¡ ȸ·ÎÀûÀ¸·Î 3.3VÀü¿ø ·¹µâ·¹ÀÌÅÍ¿Í I2C ·¹º§½¬ÇÁÅ͸¦ ³»ÀåÇÏ°í À־ 5.0V¿Í 3.3V ¿¡¼­ ¸ðµÎ »ç¿ëÀÌ °¡´É ÇÏ´Ù. STM32, ¶óÁ¸®ÆÄÀÌ µî°ú °°ÀÌ 3.3V Àü¿øÀ» »ç¿ëÇÏ´Â ÇÁ·Î¼¼¼­¿¡¼­ »ç¿ëÇÒ °æ¿ì¿¡´Â VCC ´ë½Å¿¡ 3.3V ÇÉÀ» ÅëÇؼ­ Àü¿øÀ» ¹Ù·Î ¿¬°áÇØ ÁÖ¸é µÈ´Ù.


     - Fritzing ÆÄÀÏ ´Ù¿î·Îµå

mpu9250

 



2.3 ¾ÆµÎÀÌ³ë ½ºÄÉÄ¡ ÄÚµå

´Ü¼øÈ÷ ¼¾¼­ÀÇ µ¥ÀÌÅ͸¦ ½Ã¸®¾ó µ¥ÀÌÅÍ·Î Ãâ·ÂÇÏ´Â ¿¹Á¦ ÀÌ´Ù.

(1) ¾ÆµÎÀÌ³ë ½ºÄÉÄ¡ ÄÚµå
     - ADXL345 raw µ¥ÀÌÅÍ Ç¥½Ã ½ºÄ³Ä¡ ÆÄÀÏ ´Ù¿î·Îµå

// I2C device class (I2Cdev) demonstration Arduino sketch for ADXL345 class
// 10/7/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2011-10-07 - initial release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
// I2Cdev and ADXL345 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "ADXL345.h"
// class default I2C address is 0x53
// specific I2C addresses may be passed as a parameter here
// ALT low = 0x53 (default for SparkFun 6DOF board)
// ALT high = 0x1D
ADXL345 accel;
int16_t ax, ay, az;
#define LED_PIN 13 // (Arduino is 13, Teensy is 6)
bool blinkState = false;
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
Wire.begin();
// initialize serial communication
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
// it's really up to you depending on your project)
Serial.begin(9600);
// initialize device
Serial.println("Initializing I2C devices...");
accel.initialize();
// verify connection
Serial.println("Testing device connections...");
Serial.println(accel.testConnection() ? "ADXL345 connection successful" : "ADXL345 connection failed");
// configure LED for output
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// read raw accel measurements from device
accel.getAcceleration(&ax, &ay, &az);
// display tab-separated accel x/y/z values
Serial.print("accel:\t");
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.println(az);
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}

ADXL345ÀÇ Slave Address´Â ±âº»ÀûÀ¸·Î 0x53ÀÌ°í º» Á¦Ç°¿¡¼­µµ AD0ÇÉÀÌ È¸·ÎÀûÀ¸·Î Ç® ´Ù¿î µÇ¾îÀÖ´Ù. ¸¸¾à ADXL345ÀÇ AD0ÇÉÀ» Ç®¾÷(VCC 3.3V ¿¡ ¿¬°á)À» ½ÃŲ´Ù¸é Slave Address¸¦ 0x1D·Î ¼öÁ¤ ÇÏ¿©¾ß ÇÑ´Ù.

#define ADXL345_ADDRESS_ALT_LOW 0x53

ADXL345 ¼¾¼­¸¦ ¾ÆµÎÀ̳볪 ´Ù¸¥ ¸¶ÀÌÅ©·Î ÇÁ·Î¼¼¼­¿¡¼­ µ¿½Ã¿¡ 2°³¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù¸é 1°³´Â Ç®´Ù¿î ±×´ë·Î »ç¿ëÀ» ÇÏ°í ³ª¸ÓÁö ÇÑ°³¸¦ Ç®¾÷ ½ÃÄѼ­ Slave Address¸¦ ´Ù¸£°Ô Çؼ­ »ç¿ëÀ» ÇÏ¸é µÈ´Ù.

(2) ½ÇÇà °á°ú 
ADXL345°úÀÇ I2C Åë½Å »óŸ¦ °Ë»çÇÏ°í 3ÃàÀÇ ¼¾¼­ Ãâ·Â °ªÀ» ¹Ýº¹Çؼ­ º¸¿©ÁØ´Ù.

mpu9250

º» ¸Þ´º¾óÀÇ ¾ÆµÎÀ̳ë ÄÚµå´Â ¾Æ·¡ https://github.com/jrowberg/i2cdevlib ÀÇ ³»¿ëÀ» ÂüÁ¶ÇÏ¿© ÀÛ¼º ÇÏ¿´´Ù.

3. ÇÁ·Î¼¼½ÌÀ» ÀÌ¿ëÇؼ­ 3Â÷¿ø ±×·¡ÇÈ Ç¥½Ã

3.1 ÇÁ·Î¼¼½Ì ¼³Ä¡ Çϱâ

¾ÆµÎÀ̳븦 ÀÌ¿ëÇؼ­ ¼¾¼­¿¡¼­ µ¥ÀÌÅ͸¦ ÃßÃâÇؼ­ ½Ã¸®¾ó µ¥ÀÌÅÍ·Î Ãâ·ÂÀ» Çؼ­ µ¥ÀÌÅÍ °ªÀ» È®ÀÎÀ» ½±°Ô ÇÒ ¼ö ÀÖ¾ú´Ù. ±×·¸´Ù¸é ÅؽºÆ® µ¥ÀÌÅÍ°¡ ¾Æ´Ï¶ó Á¶±Ý´õ ½Ã°¢ÀûÀΠǥÇö ¹æ¹ýÀÌ ¾øÀ»±î? ±×°Íµµ ¾ÆÁÖ ½±°Ô.. 
ÇÁ·Î¼¼½ÌÀ» ÀÌ¿ëÇÏ¸é ¾ÆµÎÀÌ³ë ½ºÄÉÄ¡ Äڵ带 ÀÔ·ÂÇϵíÀÌ ¾ÆÁÖ ½±°Ô ½Ã°¢ÀûÀΠǥÇöÀÌ °¡´ÉÇÏ´Ù. ¿ì¼± ÇÁ·Î¼¼½Ì °³¹ß ȯ°æÀ» ¼³Ä¡Çϴ°ͺÎÅÍ Çغ¸ÀÚ.

(1) ÇÁ·Î¼¼½Ì ¼³Ä¡
      - ÇÁ·Î¼¼½Ì °³¹ßȯ°æ ¼³Ä¡ Çϱâ(»õâ)

3.2 ¾ÆµÎÀ̳ë UNO R3 ¹è¼±µµ

¹è¼±µµ´Â ÀÌÀü ¿¹Á¦¿Í µ¿ÀÏÇÏ´Ù.

mpu6050

3.3 ¾ÆµÎÀÌ³ë ½ºÄÉÄ¡ ÄÚµå(3D)

(1) ¾ÆµÎÀ̳ë ÇÁ·Î¼¼½Ì ÄÚµå
ÇÁ·Î¼¼½Ì Äڵ忡¼­ ÇÑ°¡Áö ÁÖÀÇ ÇؾßÇÒ »çÇ×Àº ½Ã¸®Åë Åë½ÅÀÇ ¼Óµµ¸¦ 9600bps ·Î ¼³Á¤À» ÇÏ¿´´Ù. ±×·¸±â ¶§¹®¿¡ ¾ÆµÎÀ̳ëÀÇ ½Ã¸®¾ó ¸ð´ÏÅÍâ¿¡¼­µµ µ¿ÀÏÇÑ Åë½Å¼Óµµ¸¦ ¸ÂÃß¾î ÁÖ¾î¾ß ÇÑ´Ù.

     - ADXL345 ¾ÆµÎÀ̳ë, ÇÁ·Î¼¼½Ì ½ºÄ³Ä¡ ÆÄÀÏ ´Ù¿î·Îµå(3D)


/********************************************************************************
* ADXL345 Library Examples- pitch_roll.ino *
* *
* Copyright (C) 2012 Anil Motilal Mahtani Mirchandani(anil.mmm@gmail.com) *
* *
* License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> *
* This is free software: you are free to change and redistribute it. *
* There is NO WARRANTY, to the extent permitted by law. *
* *
*********************************************************************************/
#include <Wire.h>
#include "adxl345.h"
const float alpha = 0.5;
double fXg = 0;
double fYg = 0;
double fZg = 0;
ADXL345 acc;
void setup()
{
acc.begin();
Serial.begin(9600);
delay(100);
}
void loop()
{
double pitch, roll, Xg, Yg, Zg;
acc.read(&Xg, &Yg, &Zg);
//Low Pass Filter
fXg = Xg * alpha + (fXg * (1.0 - alpha));
fYg = Yg * alpha + (fYg * (1.0 - alpha));
fZg = Zg * alpha + (fZg * (1.0 - alpha));
//Roll & Pitch Equations
roll = (atan2(-fYg, fZg)*180.0)/M_PI;
pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg))*180.0)/M_PI;
Serial.print(pitch);
Serial.print(":");
Serial.println(roll);
delay(10);
}

¾ÆµÎÀÌ³ë ½Ã¸®¾ó ¸ð´ÏÅÍâ¿¡¼­ ¹Ýµå½Ã º¸µå·¹ÀÌÆ®(Baudate)¸¦ 9600 À¸·Î ¼öÁ¤ ÇØ¾ß ÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é ½Ã¸®¾ó ¸ð´ÏÅÍ Ã¢¿¡ ¾Æ¹«·± µ¥ÀÌÅÍ°¡ Ç¥½ÃµÇÁö ¾Ê°Å³ª À߸øµÈ µ¥ÀÌÅÍ°¡ Ç¥½ÃµÉ °ÍÀÌ´Ù. ÇÁ·Î¼¼½Ì µ¥ÀÌÅ͸¦ ó¸®Çϱâ À§ÇÑ µ¥ÀÌÅÍ À̹ǷΠµ¥ÀÌÅ͸¦ ¹Ù·Î Æǵ¶Çϱâ´Â ¾î·Æ´Ù. µ¥ÀÌÅÍ°¡ ¿Ã¹Ù¸£°Ô Ç¥½ÃµÇ´Â°ÍÀ» È®ÀÎ ÇÏ¿´´Ù¸é ÇÁ·Î¼¼½Ì¿¡¼­ µ¿ÀÏÇÑ ½Ã¸®¾óÆ÷Æ®¸¦ »ç¿ëÇØ¾ß Çϱ⠶§¹®¿¡ ¾ÆµÎÀÌ³ë ½Ã¸®¾ó ¸ð´ÏÅÖ Ã¢À» ´Ýµµ·Ï ÇÏÀÚ.

3.4 ÇÁ·Î¼¼½Ì ÄÚµå(3D)

ÇÁ·Î¼¼½Ì Äڵ忡¼­ ÇÑ°¡Áö ÁÖÀÇ ÇؾßÇÒ »çÇ×Àº ½Ã¸®¾ó Æ÷Æ®¸¦ °¢ÀÚÀÇ È¯°æ¿¡ ¸ÂÃ߾ ¼öÁ¤À» ÇØÁÖ¾î¾ß ÇÑ´Ù´Â °ÍÀÌ´Ù.
¾Æ·¡ ÇÁ·Î¼¼½Ì Äڵ忡¼­ "[0]" ÀÇ 0À̶ó´Â ¼ýÀÚ´Â ÀåÄ¡°ü¸®ÀÚ¿¡¼­ COMÆ÷Æ®ÀÇ ¹øÈ£°¡ ¾Æ´Ï¶ó Æ÷Æ®ÀÇ ¼ø¼­¶ó´Â°Í¿¡ ÁÖÀÇ ÇØ¾ß ÇÑ´Ù.

mpu6050

À§ÀÇ ÀåÄ¡°ü¸®ÀÚ È­¸é¿¡¼­ ¿¹¸¦ µç´Ù¸é ´ÙÀ½°ú °°´Ù.

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

ÇÁ·Î¼¼½Ì Äڵ带 ½ÇÇàÇÒ¶§ Å×½ºÆ®ÇÏ´Â PCÀÇ COM Æ÷Æ® »óÅ¿¡ µû¶ó¼­ "Serial.list()[0]" ÀÇ ¼ýÀÚ¸¦ ¹Ù²Ù¾î ÁÖ¾î¾ß ÇÑ´Ù.

(1) ÇÁ·Î¼¼½Ì ÄÚµå

/********************************************************************************
* ADXL345 Library Examples- pitch_roll.pde *
* *
* Copyright (C) 2012 Anil Motilal Mahtani Mirchandani(anil.mmm@gmail.com) *
* *
* License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> *
* This is free software: you are free to change and redistribute it. *
* There is NO WARRANTY, to the extent permitted by law. *
* *
*********************************************************************************/
// If you are working with Arduino Mega
// sudo ln -s /dev/ttyACM0 /dev/ttyS8
import processing.serial.*;
Serial fd;
int pitch = 0;
int roll = 0;
void setup () {
size(640, 360, P3D); //Connect to the corresponding serial port
fd = new Serial(this, Serial.list()[0], 9600);
// Defer callback until new line
fd.bufferUntil('\n');
}
void draw () {
//Set background
background(0.5);
pushMatrix(); translate(width/2, height/2, -30); //Rotate
rotateX(((float)pitch)*PI/180.0); rotateZ(((float)roll)*PI/180.0); //Print data
print("Pitch: ");
print(pitch);
print(", Roll: ");
println(roll);
scale(90);
beginShape(QUADS);
fill(0, 255, 0); vertex(-1, 1, 1);
fill(0, 255, 0); vertex( 1, 1, 1);
fill(0, 255, 0); vertex( 1, -1, 1);
fill(0, 255, 0); vertex(-1, -1, 1);
fill(0, 255, 255); vertex( 1, 1, 1);
fill(0, 255, 255); vertex( 1, 1, -1);
fill(0, 255, 255); vertex( 1, -1, -1);
fill(0, 255, 255); vertex( 1, -1, 1);
fill(255, 0, 255); vertex( 1, 1, -1);
fill(255, 0, 255); vertex(-1, 1, -1);
fill(255, 0, 255); vertex(-1, -1, -1);
fill(255, 0, 255); vertex( 1, -1, -1);
fill(255, 255, 0); vertex(-1, 1, -1);
fill(255, 255, 0); vertex(-1, 1, 1);
fill(255, 255, 0); vertex(-1, -1, 1);
fill(255, 255, 0); vertex(-1, -1, -1);
fill(255, 0, 0); vertex(-1, 1, -1);
fill(255, 0, 0); vertex( 1, 1, -1);
fill(255, 0, 0); vertex( 1, 1, 1);
fill(255, 0, 0); vertex(-1, 1, 1);
fill(0, 0, 255); vertex(-1, -1, -1);
fill(0, 0, 255); vertex( 1, -1, -1);
fill(0, 0, 255); vertex( 1, -1, 1);
fill(0, 0, 255); vertex(-1, -1, 1);
endShape();
popMatrix(); }
void serialEvent (Serial fd) {
// get the ASCII string:
String rpstr = fd.readStringUntil('\n');
if (rpstr != null) {
String[] list = split(rpstr, ':');
pitch = ((int)float(list[0]));
roll = ((int)float(list[1]));
}
}

(2) ½ÇÇà °á°ú



º» ¸Þ´º¾óÀÇ ÇÁ·Î¼¼½Ì ÄÚµå´Â ¾Æ·¡ URLÀÇ ³»¿ëÀ» ÂüÁ¶ÇÏ¿© ÀÛ¼º ÇÏ¿´´Ù.
https://theccontinuum.com/2012/09/24/arduino-imu-pitch-roll-from-accelerometer/

3.5 ¾ÆµÎÀÌ³ë ½ºÄÉÄ¡ ÄÚµå(2D)

(1) ¾ÆµÎÀ̳ë ÇÁ·Î¼¼½Ì ÄÚµå
ÇÁ·Î¼¼½Ì Äڵ忡¼­ ÇÑ°¡Áö ÁÖÀÇ ÇؾßÇÒ »çÇ×Àº ½Ã¸®Åë Åë½ÅÀÇ ¼Óµµ¸¦ 115200bps ·Î ¼³Á¤À» ÇÏ¿´´Ù. ±×·¸±â ¶§¹®¿¡ ¾ÆµÎÀ̳ëÀÇ ½Ã¸®¾ó ¸ð´ÏÅÍâ¿¡¼­µµ µ¿ÀÏÇÑ Åë½Å¼Óµµ¸¦ ¸ÂÃß¾î ÁÖ¾î¾ß ÇÑ´Ù.

     - ADXL345 ¾ÆµÎÀ̳ë, ÇÁ·Î¼¼½Ì ½ºÄ³Ä¡ ÆÄÀÏ ´Ù¿î·Îµå(2D)


/*
ADXL345 Triple Axis Accelerometer. Output for ADXL345_processing.pde
Read more: http://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-akcelerometr-adxl345.html
GIT: https://github.com/jarzebski/Arduino-ADXL345
Web: http://www.jarzebski.pl
(c) 2014 by Korneliusz Jarzebski
*/
#include <Wire.h>
#include "adxl345.h"
ADXL345 accelerometer;
void setup(void) {
Serial.begin(115200);
// Initialize ADXL345
if (!accelerometer.begin())
{
delay(500);
}
// Set measurement range
// +/- 2G: ADXL345_RANGE_2G
// +/- 4G: ADXL345_RANGE_4G
// +/- 8G: ADXL345_RANGE_8G
// +/- 16G: ADXL345_RANGE_16G
accelerometer.setRange(ADXL345_RANGE_16G);
}
void loop(void) {
// Read normalized values
Vector norm = accelerometer.readNormalize();
// Low Pass Filter to smooth out data. 0.1 - 0.9
Vector filtered = accelerometer.lowPassFilter(norm, 0.15);
// Calculate Pitch & Roll
int pitch = -(atan2(norm.XAxis, sqrt(norm.YAxis*norm.YAxis + norm.ZAxis*norm.ZAxis))*180.0)/M_PI;
int roll = (atan2(norm.YAxis, norm.ZAxis)*180.0)/M_PI;
// Calculate Pitch & Roll (Low Pass Filter)
int fpitch = -(atan2(filtered.XAxis, sqrt(filtered.YAxis*filtered.YAxis + filtered.ZAxis*filtered.ZAxis))*180.0)/M_PI;
int froll = (atan2(filtered.YAxis, filtered.ZAxis)*180.0)/M_PI;
// Output
Serial.print(pitch);
Serial.print(":");
Serial.print(roll);
Serial.print(":");
// Output (filtered)
Serial.print(fpitch);
Serial.print(":");
Serial.print(froll);
Serial.println();
}

¾ÆµÎÀÌ³ë ½Ã¸®¾ó ¸ð´ÏÅÍâ¿¡¼­ ¹Ýµå½Ã º¸µå·¹ÀÌÆ®(Baudate)¸¦ 115200 À¸·Î ¼öÁ¤ ÇØ¾ß ÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é ½Ã¸®¾ó ¸ð´ÏÅÍ Ã¢¿¡ ¾Æ¹«·± µ¥ÀÌÅÍ°¡ Ç¥½ÃµÇÁö ¾Ê°Å³ª À߸øµÈ µ¥ÀÌÅÍ°¡ Ç¥½ÃµÉ °ÍÀÌ´Ù. ÇÁ·Î¼¼½Ì µ¥ÀÌÅ͸¦ ó¸®Çϱâ À§ÇÑ µ¥ÀÌÅÍ À̹ǷΠµ¥ÀÌÅ͸¦ ¹Ù·Î Æǵ¶Çϱâ´Â ¾î·Æ´Ù. µ¥ÀÌÅÍ°¡ ¿Ã¹Ù¸£°Ô Ç¥½ÃµÇ´Â°ÍÀ» È®ÀÎ ÇÏ¿´´Ù¸é ÇÁ·Î¼¼½Ì¿¡¼­ µ¿ÀÏÇÑ ½Ã¸®¾óÆ÷Æ®¸¦ »ç¿ëÇØ¾ß Çϱ⠶§¹®¿¡ ¾ÆµÎÀÌ³ë ½Ã¸®¾ó ¸ð´ÏÅÖ Ã¢À» ´Ýµµ·Ï ÇÏÀÚ.

3.4 ÇÁ·Î¼¼½Ì ÄÚµå(2D)

(1) ÇÁ·Î¼¼½Ì ÄÚµå

/*
ADXL345 Triple Axis Accelerometer. Processing for ADXL345_processing.ino
Read more: http://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-akcelerometr-adxl345.html
GIT: https://github.com/jarzebski/Arduino-ADXL345
Web: http://www.jarzebski.pl
(c) 2014 by Korneliusz Jarzebski
*/
import processing.serial.*;
Serial myPort;
// Data samples
int actualSample = 0;
int maxSamples = 400;
int sampleStep = 1;
boolean hasData = false;
// Charts
PGraphics pgChart;
int[] colors = { #ff4444, #33ff99, #5588ff };
String[] pyrSeries = { "Pitch", "Roll" };
String[] compareSeries = { "Normal", "Filtered" };
// Data for accelerometer Pitch, Roll
float[][] pyrValues = new float[2][maxSamples];
float[][] pyrValuesFiltered = new float[2][maxSamples];
// Data for compare
float[][] pitchValues = new float[2][maxSamples];
float[][] rollValues = new float[2][maxSamples];
// Artificial Horizon
PGraphics pgArtificialHorizon;
PGraphics pgArtificialHorizonRing;
PImage imgArtificialHorizon;
PImage imgArtificialHorizonRing;
int ahWidth = 0;
int ahHeight = 0;
int ahDiameter = 0;
int ahRadius = 0;
float ahKappa = 0.5522847498;
float ahRadiusKappa = 0;
void setup ()
{
size(755, 550, P2D);
background(0);
// Init
initArtificialHorizon();
// Serial
myPort = new Serial(this, Serial.list()[0], 115200);
myPort.bufferUntil(10);
}
void drawChart(String title, String[] series, float[][] chart, int x, int y, int h, boolean symmetric, boolean fixed, int fixedMin, int fixedMax, int hlines) {
int actualColor = 0;
int maxA = 0;
int maxB = 0;
int maxAB = 0;
int min = 0;
int max = 0;
int step = 0;
int divide = 0;
if (fixed)
{
min = fixedMin;
max = fixedMax;
step = hlines;
} else
{
if (hlines > 2)
{
divide = (hlines - 2);
} else
{
divide = 1;
}
if (symmetric)
{
maxA = (int)abs(getMin(chart));
maxB = (int)abs(getMax(chart));
maxAB = max(maxA, maxB);
step = (maxAB * 2) / divide;
min = -maxAB-step;
max = maxAB+step;
} else
{
min = (int)(getMin(chart));
max = (int)(getMax(chart));
if ((max >= 0) && (min <= 0)) step = (abs(min) + abs(max)) / divide; if ((max < 0) && (min < 0)) step = abs(min - max) / divide; if ((max > 0) && (min > 0)) step = (max - min) / divide; if (divide > 1)
{
min -= step;
max += step;
}
}
}
pgChart = createGraphics((maxSamples*sampleStep)+50, h+60);
pgChart.beginDraw();
// Draw chart area and title
pgChart.background(0);
pgChart.strokeWeight(1);
pgChart.noFill();
pgChart.stroke(50);
pgChart.rect(0, 0, (maxSamples*sampleStep)+49, h+59);
pgChart.text(title, ((maxSamples*sampleStep)/2)-(textWidth(title)/2)+40, 20);
// Draw chart description
String Description[] = new String[chart.length];
int DescriptionWidth[] = new int[chart.length];
int DesctiptionTotalWidth = 0;
int DescriptionOffset = 0;
for (int j = 0; j < chart.length; j++)
{
Description[j] = " "+series[j]+" = ";
DescriptionWidth[j] += textWidth(Description[j]+"+000.00");
Description[j] += nf(chart[j][actualSample-1], 0, 2)+" ";
DesctiptionTotalWidth += DescriptionWidth[j];
}
actualColor = 0;
for (int j = 0; j < chart.length; j++)
{
pgChart.fill(colors[actualColor]);
pgChart.text(Description[j], ((maxSamples*sampleStep)/2)-(DesctiptionTotalWidth/2)+DescriptionOffset+40, h+50);
DescriptionOffset += DescriptionWidth[j];
actualColor++;
if (actualColor >= colors.length) actualColor = 0;
}
// Draw H-Lines
pgChart.stroke(100);
for (float t = min; t <= max; t=t+step)
{
float line = map(t, min, max, 0, h);
pgChart.line(40, h-line+30, (maxSamples*sampleStep)+40, h-line+30);
pgChart.fill(200, 200, 200);
pgChart.textSize(12);
pgChart.text(int(t), 5, h-line+34);
}
// Draw data series
pgChart.strokeWeight(2);
for (int i = 1; i < actualSample; i++)
{
actualColor = 0;
for (int j = 0; j < chart.length; j++)
{
pgChart.stroke(colors[actualColor]);
float d0 = chart[j][i-1];
float d1 = chart[j][i];
if (d0 < min) d0 = min;
if (d0 > max) d0 = max;
if (d1 < min) d1 = min;
if (d1 > max) d1 = max;
float v0 = map(d0, min, max, 0, h);
float v1 = map(d1, min, max, 0, h);
pgChart.line(((i-1)*sampleStep)+40, h-v0+30, (i*sampleStep)+40, h-v1+30);
actualColor++;
if (actualColor >= colors.length) actualColor = 0;
}
}
pgChart.endDraw();
image(pgChart, x, y);
}
void initArtificialHorizon()
{
imgArtificialHorizon = loadImage("artificialHorizon.png");
imgArtificialHorizonRing = loadImage("artificialHorizonRing.png");
ahWidth = imgArtificialHorizon.width - 20;
ahHeight = imgArtificialHorizon.height - 20;
ahDiameter = min(ahWidth, ahHeight);
ahRadius = ahDiameter / 2;
ahRadiusKappa = ahRadius * ahKappa;
}
float getArtificialHorizon(float pitch)
{
return -sin(pitch)*ahRadius;
}
void drawScale(float offset, float[][] pyr)
{
float horizon;
// Ground side
horizon = getArtificialHorizon(radians(pyr[0][actualSample-1]) - offset * PI / 180);
pgArtificialHorizon.noFill();
pgArtificialHorizon.beginShape();
pgArtificialHorizon.vertex(ahRadius, 0);
pgArtificialHorizon.stroke(255);
pgArtificialHorizon.strokeWeight(2);
pgArtificialHorizon.bezierVertex(ahRadius, horizon * ahKappa, ahRadiusKappa, horizon, 0, horizon);
pgArtificialHorizon.bezierVertex( -ahRadiusKappa, horizon, -ahRadius, horizon * ahKappa, -ahRadius, 0);
pgArtificialHorizon.endShape();
// Sky side
horizon = getArtificialHorizon(radians(pyr[0][actualSample-1]) + offset * PI / 180);
pgArtificialHorizon.noFill();
pgArtificialHorizon.beginShape();
pgArtificialHorizon.vertex(ahRadius, 0);
pgArtificialHorizon.stroke(0);
pgArtificialHorizon.strokeWeight(2);
pgArtificialHorizon.bezierVertex(ahRadius, horizon * ahKappa, ahRadiusKappa, horizon, 0, horizon);
pgArtificialHorizon.bezierVertex( -ahRadiusKappa, horizon, -ahRadius, horizon * ahKappa, -ahRadius, 0);
pgArtificialHorizon.endShape();
}
void drawArtificialHorizon(int x, int y, float[][] pyr)
{
pgArtificialHorizon = createGraphics(ahWidth, ahHeight);
pgArtificialHorizonRing = createGraphics(ahWidth+20, ahHeight+20); float horizon = getArtificialHorizon(radians(pyr[0][actualSample-1]));
// pgArtificialHorizon.clear();
pgArtificialHorizon.beginDraw();
// Ground
pgArtificialHorizon.translate(ahRadius, ahRadius);
pgArtificialHorizon.rotate(radians(-pyr[1][actualSample-1]));
pgArtificialHorizon.strokeWeight(0);
pgArtificialHorizon.fill(40, 40, 40);
pgArtificialHorizon.arc(0.0, 0.0, ahDiameter, ahDiameter, 0, 2 * PI);
// Sky
pgArtificialHorizon.beginShape();
pgArtificialHorizon.fill(200, 200, 250);
pgArtificialHorizon.strokeWeight(2);
pgArtificialHorizon.stroke(255);
pgArtificialHorizon.vertex(-ahRadius, 0);
pgArtificialHorizon.bezierVertex(-ahRadius, -ahRadius-20, ahRadius, -ahRadius-20, ahRadius, 0);
pgArtificialHorizon.bezierVertex(ahRadius, horizon * ahKappa, ahRadiusKappa, horizon, 0, horizon);
pgArtificialHorizon.bezierVertex(-ahRadiusKappa, horizon, -ahRadius, horizon * ahKappa, -ahRadius, 0);
pgArtificialHorizon.endShape();
// Scale
drawScale(60, pyr);
drawScale(50, pyr);
drawScale(40, pyr);
drawScale(30, pyr);
drawScale(20, pyr);
drawScale(10, pyr);
pgArtificialHorizon.endDraw();
image(pgArtificialHorizon, x+10, y+10);
image(imgArtificialHorizon, x, y);
// Draw ring
pgArtificialHorizonRing.beginDraw();
pgArtificialHorizonRing.clear();
pgArtificialHorizonRing.translate(130,130);
pgArtificialHorizonRing.rotate(radians(pyr[1][actualSample-1]));
pgArtificialHorizonRing.image(imgArtificialHorizonRing, -130, -130);
pgArtificialHorizonRing.endDraw();
image(pgArtificialHorizonRing, x, y);
}
float getMin(float[][] chart)
{
float minValue = 0;
float[] testValues = new float[chart.length];
float testMin = 0;
for (int i = 0; i < actualSample; i++)
{
for (int j = 0; j < testValues.length; j++)
{
testValues[j] = chart[j][i];
}
testMin = min(testValues);
if (i == 0)
{
minValue = testMin;
} else
{
if (minValue > testMin) minValue = testMin;
}
}
return ceil(minValue)-1; }
float getMax(float[][] chart)
{
float maxValue = 0;
float[] testValues = new float[chart.length];
float testMax = 0;
for (int i = 0; i < actualSample; i++)
{
for (int j = 0; j < testValues.length; j++)
{
testValues[j] = chart[j][i];
}
testMax = max(testValues);
if (i == 0)
{
maxValue = testMax;
} else
{
if (maxValue < testMax) maxValue = testMax;
}
}
return ceil(maxValue); }
void draw() {
if (!hasData) return;
background(0);
drawChart("Pitch [deg]", compareSeries, pitchValues, 10, 10, 200, true, true, -90, 90, 30);
drawChart("Roll [deg]", compareSeries, rollValues, 10, 280, 200, true, true, -90, 90, 30);
drawArtificialHorizon(480, 20, pyrValues);
drawArtificialHorizon(480, 290, pyrValuesFiltered);
}
void nextSample(float[][] chart)
{
for (int j = 0; j < chart.length; j++)
{
float last = chart[j][maxSamples-1];
for (int i = 1; i < maxSamples; i++)
{
chart[j][i-1] = chart[j][i];
}
chart[j][(maxSamples-1)] = last;
}
}
void serialEvent (Serial myPort)
{
String inString = myPort.readStringUntil(10);
if (inString != null)
{
inString = trim(inString);
String[] list = split(inString, ':');
String testString = trim(list[0]);
if (list.length != 4) return;
// Fill Pitch & Roll
pyrValues[0][actualSample] = (float(list[0]));
pyrValues[1][actualSample] = (float(list[1]));
// Fill Pitch & Roll (Filtered)
pyrValuesFiltered[0][actualSample] = (float(list[2]));
pyrValuesFiltered[1][actualSample] = (float(list[3]));
// Fill Pitch compare
pitchValues[0][actualSample] = (float(list[0]));
pitchValues[1][actualSample] = (float(list[2]));
// Fill Roll compare
rollValues[0][actualSample] = (float(list[1]));
rollValues[1][actualSample] = (float(list[3]));
if (actualSample > 1)
{
hasData = true;
}
if (actualSample == (maxSamples-1))
{
nextSample(pyrValues);
nextSample(pyrValuesFiltered);
nextSample(pitchValues);
nextSample(rollValues);
} else
{
actualSample++;
}
}
}

(2) ½ÇÇà °á°ú



º» ¸Þ´º¾óÀÇ ÇÁ·Î¼¼½Ì ÄÚµå´Â ¾Æ·¡ URLÀÇ ³»¿ëÀ» ÂüÁ¶ÇÏ¿© ÀÛ¼º ÇÏ¿´´Ù.
https://theccontinuum.com/2012/09/24/arduino-imu-pitch-roll-from-accelerometer/

* ´Ù¸¥ ¼¾¼­µéÀÇ ¾ÆµÎÀ̳ë¿Í ÇÁ·Î¼¼½Ì ¸Þ´º¾ó º¸±â

(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 ¼¾¼­ ¾ÆµÎÀ̳ë, ÇÁ·Î¼¼½Ì ¸Þ´º¾ó(»õâ)