Arduino와 ADXL345 3축 가속도 센서를 활용한 다양한 실험
Arduino 플랫폼에서 사용 가능한 수많은 센서 모듈 중 ADXL345 3축 가속도 센서는 특히 인기 있는 선택이다. 이 센서는 I2C 또는 SPI 통신을 통해 3차원 공간에서의 가속도를 정밀하게 측정할 수 있으며, 기울기 감지, 충격 탐지, 진동 분석 등 다양한 응용에 적합하다.
실험 1: ADXL345 라이브러리를 이용한 각도 측정 및 보정
이 실험에서는 ADXL345_WE 라이브러리를 사용하여 정확한 각도 측정과 보정을 수행한다. 센서는 I2C 프로토콜을 사용하며, A4 핀이 데이터선(SDA), A5 핀이 클럭선(SCL)으로 연결된다.
#include <Wire.h>
#include <ADXL345_WE.h>
#define ACCELEROMETER_ADDRESS 0x53
ADXL345_WE sensor = ADXL345_WE(ACCELEROMETER_ADDRESS);
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("가속도 센서 테스트 시작");
if (!sensor.initialize()) {
Serial.println("센서 연결 확인 필요");
return;
}
// 보정 계수 설정 (이전 보정 프로그램에서 얻은 값)
sensor.setCalibrationFactors(-268.0, 283.0, -270.0, 276.0, -289.0, 216.0);
Serial.println("센서를 평면에 수평으로 놓고 2초 대기");
delay(2000);
sensor.calculateAngleOffset();
Serial.println("보정 완료");
sensor.setDataRate(ADXL345_DATA_RATE_50);
Serial.print("데이터 전송 속도: ");
Serial.print(sensor.getDataRateString());
sensor.setMeasurementRange(ADXL345_RANGE_2G);
Serial.print(" / 측정 범위: ");
Serial.println(sensor.getRangeString());
}
void loop() {
xyzFloat rawData = sensor.getRawAcceleration();
xyzFloat gravityData = sensor.getGravityValues();
xyzFloat angles = sensor.getTiltAngles();
xyzFloat correctedAngles = sensor.getCorrectedAngles();
Serial.print("원시 X = ");
Serial.print(rawData.x);
Serial.print(" | 원시 Y = ");
Serial.print(rawData.y);
Serial.print(" | 원시 Z = ");
Serial.println(rawData.z);
Serial.print("중력 X = ");
Serial.print(gravityData.x);
Serial.print(" | 중력 Y = ");
Serial.print(gravityData.y);
Serial.print(" | 중력 Z = ");
Serial.println(gravityData.z);
Serial.print("각도 X = ");
Serial.print(angles.x);
Serial.print(" | 각도 Y = ");
Serial.print(angles.y);
Serial.print(" | 각도 Z = ");
Serial.println(angles.z);
Serial.print("보정 각도 X = ");
Serial.print(correctedAngles.x);
Serial.print(" | 보정 각도 Y = ");
Serial.print(correctedAngles.y);
Serial.print(" | 보정 각도 Z = ");
Serial.println(correctedAngles.z);
Serial.print("방향 상태: ");
Serial.println(sensor.getDirectionString());
delay(500);
}
실험 2: LED 매트릭스를 활용한 가속도 시각화
이 실험은 8x8 LED 매트릭스와 ADXL345 센서를 결합하여 가속도 방향을 시각적으로 표현한다. 센서의 값을 매핑하여 LED 매트릭스 상의 점을 이동시키는 효과를 구현한다.
#include <LedControl.h>
#include <Wire.h>
#define SENSOR_ADDR 0x53
#define READ_BYTES 6
byte buffer[READ_BYTES];
LedControl ledMatrix = LedControl(12, 10, 11, 1);
unsigned long refreshDelay = 50;
class GravityPoint {
public:
int posX = 0;
int posY = 0;
int weight = 1;
};
GravityPoint *gravityObject;
void setup() {
gravityObject = new GravityPoint();
initializeDisplay();
Wire.begin();
Serial.begin(9600);
configureSensor(SENSOR_ADDR, 0x2D, 0);
configureSensor(SENSOR_ADDR, 0x2D, 16);
configureSensor(SENSOR_ADDR, 0x2D, 8);
}
void loop() {
int startRegister = 0x32;
int accX, accY, accZ;
readAccelerationData(SENSOR_ADDR, startRegister, READ_BYTES, buffer);
accX = combineBytes(buffer[1], buffer[0]);
accY = combineBytes(buffer[3], buffer[2]);
accZ = combineBytes(buffer[5], buffer[4]);
accX = mapValue(accX, -300, 300, 0, 8);
accY = mapValue(accY, -300, 300, 0, 8);
accZ = mapValue(accZ, -300, 300, 0, 8);
Serial.print("X축: ");
Serial.print(accX);
Serial.print(" Y축: ");
Serial.print(accY);
Serial.print(" Z축: ");
Serial.println(accZ);
clearMatrix();
gravityObject->posX = constrain(accX, 0, 7);
gravityObject->posY = constrain(accY, 0, 7);
ledMatrix.setLed(0, gravityObject->posX, gravityObject->posY, true);
delay(10);
}
void initializeDisplay() {
int deviceCount = ledMatrix.getDeviceCount();
for (int addr = 0; addr < deviceCount; addr++) {
ledMatrix.shutdown(addr, false);
ledMatrix.setIntensity(addr, 1);
ledMatrix.clearDisplay(addr);
}
}
void configureSensor(int deviceAddr, byte reg, byte value) {
Wire.beginTransmission(deviceAddr);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
void readAccelerationData(int deviceAddr, byte reg, int count, byte* outputBuffer) {
Wire.beginTransmission(deviceAddr);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(deviceAddr, count);
int index = 0;
while (Wire.available()) {
outputBuffer[index] = Wire.read();
index++;
}
delay(10);
}
int combineBytes(byte highByte, byte lowByte) {
return ((int)highByte << 8) | lowByte;
}
int mapValue(int input, int inMin, int inMax, int outMin, int outMax) {
return (input - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
void clearMatrix() {
ledMatrix.clearDisplay(0);
}
실험 3: 가속도 센서를 통한 LED 제어
이 간단한 실험에서는 ADXL345 센서의 가속도 값을 기준으로 아두이노의 내장 LED(D13 핀)를 제어한다. 특정 축의 가속도가 임계값을 초과하면 LED가 점등된다.
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#define LED_PORT 13
Adafruit_ADXL345_Unified accelerometer = Adafruit_ADXL345_Unified();
void setup() {
Serial.begin(9600);
Serial.println("가속도 센서 기반 LED 제어");
if (!accelerometer.begin()) {
Serial.println("가속도 센서 인식 실패");
while (1);
}
pinMode(LED_PORT, OUTPUT);
}
void loop() {
sensors_event_t dataEvent;
accelerometer.getEvent(&dataEvent);
float xAxis = dataEvent.acceleration.x;
float yAxis = dataEvent.acceleration.y;
float zAxis = dataEvent.acceleration.z;
Serial.print("X: ");
Serial.print(xAxis);
Serial.print(" ");
Serial.print("Y: ");
Serial.print(yAxis);
Serial.print(" ");
Serial.print("Z: ");
Serial.print(zAxis);
Serial.println(" m/s²");
if (abs(xAxis) > 5.0) {
digitalWrite(LED_PORT, HIGH);
Serial.println("X축 임계치 초과 - LED ON");
} else if (abs(yAxis) > 5.0) {
digitalWrite(LED_PORT, HIGH);
Serial.println("Y축 임계치 초과 - LED ON");
} else {
digitalWrite(LED_PORT, LOW);
}
delay(500);
}