개발자/Arduino

미세진동 측정 - LSM6DS3 가속도계 자이로 센서를 이용

지구빵집 2020. 11. 11. 19:57
반응형

 

 

시간을 더 많이 낭비하고, 일을 더 많이 하다 보니 생각은 줄어들고 배우는 것이 많아져 기술 포스팅을 많이 하는 시절이다. 잘 된 일인지 좋은 일인지 모르겠다. 너무 열심히 일하느라 돈 벌 시간이 없는 점만 주의하면 좋은 일이라고 생각한다. 

 

생각을 극도로 단순화할 때 가장 좋은 단순한 해결방법이 나온다. 엄청 고민하고 좀 쉽게 해결해보겠다는 생각으로 여러 예제 코드와 라이브러리들을 찾느라 시간을 다 보냈다. 다시 가장 처음으로 돌아왔다. LSM6DS3 관성 센서(IMU, Inertia Measurement Unit)에서 나오는  값들을 아두이노 IDE 스케치에서 시리얼 플로터에 그렸다. 단순히 값을 프린트해 보면서 복잡한 연산이나 적분도 필요 없이 이전 값과 현재 값을 비교하는 방법을 적용하기로 했다. 얼마나 단순한지 다람쥐가 도토리를 감추는 방법으로도 활용할 만한 방법이다. 

 

진동의 유무를 알기 위해 LSM6DS3 센서에서 Accelerometer 센서 출력 값을 그래프로 그려보니 미세하게 진동이 있을 때와 정지하고 있을 때의 차이가 보인다. 현재 포스팅을 이해하면 다른 여러 가지 방법으로 응용이 가능하다. 현재 센서가 박힌 물체의 자세와 운동을 값을 통해 비교하고 이전 자세와 어떤 차이가 있는 지를 실제로 확인하며 적용할 수 있다.

 

어떤 자세로 있든지 아주 미세한 진동이라도 생기면 그래프 x, y, z 축 값이 변한다는 사실이다. 물론 조금도 아주 조금도 움직이지 않으면 값은 변하지 않는다. 아니 움직이지 않아도 바람이 불어서라도 값은 변하는 경우가 있다. 우리가 무시하면 될 정도의 값은 무시하기로 한다.

 

이 방법의 주요 생각은 움직이지 않을 때는 x, y, z 방향 어느 값도 변하지 않는다는 사실이다. 물론 운동이 시작되고 운동이 끝나는 지점에서 값은 점점 안정화하는 추세에 있으니 여전히 센서 값은 변한기도 한다. 일단정지 상태에 있으면 고정된 값만을 읽을 수 있고, 진동이 있으면 변화되는 값을 얻는다. 변화한 차이가 아니라 값이 변한다는 사실에 입각한 센서 값을 얻는다. 이 값을 이전에 읽어 저장한 값과 비교해서 일정한 시간 동안 변한 횟수를 측정하여 진동의 유무를 알아낸다.  

 

어떤 관성 센서를 사용해도 아이디어는 변함이 없다. 여기서는 Nano 33 IoT 보드에 있는 6축 관성센서인 LSM6DS3 센서를 사용한다. 일단 아두이노 IDE에서 메뉴 - 툴 - 라이브러리 관리자로 들어간다. 검색창에서 LSM6 DS3을 찾아 아래 이름을 가진 라이브러리를 찾아 설치한다. 이게 기본이고 그 외 많은 라이브러리가 존재한다. 라이브러리가 설치된 폴더는 아마도 C:\Users\USER\Documents\Arduino\libraries\Arduino_LSM6DS3 일 확률이 크다. 이게 왜 중요하냐면 나중에 "SmartEverything LSM6 DS3"이라는 라이브러리를 사용하면 라이브러리 충돌 에러가 나는데 이때 여기서 폴더 둘 중 하나를 지워야 한다. 하여튼 그렇다. 

 

LSM6DS3 를 찾아 아래 이름을 가진 라이브러리를 찾아 설치

그래프를 그려주는 가장 간단한 예제이자 기초이면서 시작하는 코드인 SimpleAccelerometer 예제를 불러온다. 아래 그림을 참조하세요.

 

SimpleAccelerometer 예제

 

예제 소스코드는 아래와 같다. 코드가 작년 7월 배포되었고, LSM6DS3에서 가속센서 값을 읽고, 직렬 모니터와 직렬 플로터에 지속적으로 인쇄하고 적용 회로는 Arduino Uno WiFi Rev 2 또는 Arduino Nano 33 IoT 회로라고 설명한다. 이렇게 최근 코드를 만나면 괜히 흥분되고, 심장이 벌렁벌렁 뛰고 기대감이 충만하게 되는 이유가 무엇일까? 마치 우리는 태어날 때부터 프로그래머(뜻은 미리 그려서 보여주는 사람, 예언자)가 되도록 프로그램된 게 아닐까 하는 생각이 든다. :) 컴파일하고 업로드한다. 코드 아래에 보이는 아름다운 그래프를 볼 수 있다면 다 끝낸 것이다. 축하한다!

 

/*
  Arduino LSM6DS3 - Simple Accelerometer

  This example reads the acceleration values from the LSM6DS3
  sensor and continuously prints them to the Serial Monitor
  or Serial Plotter.

  The circuit:
  - Arduino Uno WiFi Rev 2 or Arduino Nano 33 IoT

  created 10 Jul 2019
  by Riccardo Rizzo

  This example code is in the public domain.
*/

#include <Arduino_LSM6DS3.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");

    while (1);
  }

  Serial.print("Accelerometer sample rate = ");
  Serial.print(IMU.accelerationSampleRate());
  Serial.println(" Hz");
  Serial.println();
  Serial.println("Acceleration in G's");
  Serial.println("X\tY\tZ");
}

void loop() {
  float x, y, z;

  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);

    Serial.print(x);
    Serial.print('\t');
    Serial.print(y);
    Serial.print('\t');
    Serial.println(z);
  }
  //delay(1000);
}

 

그래프의 색이나 순서, 값도 아직은 생각하지 않아도 된다. 무시다. 아래 사진이 센서를 마구 움직일 때 그래프인데 척 보면 Nno 33 IoT 보드를 길이로 놓고 수평일 때, 옆으로 세웠을 때, 마지막 길이 방향으로 세웠을 때 각각 x, y, z 값이 주도적으로 크게 나온다. 그러니까 수평을 유지하면 X값이 크게 나오고 다른 두 방향 값은 작은 값이거나 값의 변화하는 것도 줄어든다. 다른 축도 마찬가지다. 역시나 색 순서도 바뀐다. -값도 나온다. 우리는 진동을 알아내려는 것이라서 어떻게 움직이는지 각도가 먼지 이런 것은 생각하지 않는다. 각 그래프의 특징만 기억하고 제가 힘들어서 맨 아래 진동 감지하는 코드를 설명합니다. 별것 없습니다. 

 

마구 움직일 때 엉망인 데이터

 

진동이 전혀 없을 때 데이터

 

위 이미지와 아래 이미지는 참 아름답죠? 아주 미세한 진동으로 값이 변하는 것을 아주 잘 보여줍니다. 마치 조약돌 하나가 호숫가 전체에 큰 파도를 만들어 내는 것처럼 말입니다. 장윤정 가수가 부른 초혼이란 가사에 나오는 구절이 생각납니다. "스치듯 보낼 사람이 어쩌다 내게 들어 와 장미의 가시로 남아서 날 아프게 지켜보네요." 

 

 

아주 미세한 진동이라도 있을 경우 데이터

 

잘 오셨습니다. 센서값은 float 값입니다. 단순하게 소수점 값이라는 말이죠. double, float 값은 아기 다루듯 굉장히 조심스럽게 다루어야 합니다. 막 비교를 한다든가, 기준 값으로 쓴다든가 값을 가지고 다른 데 쓰려고 하다가는 진짜 고생합니다. 아예 형 변환을 해버리든가 도망가시기를 권합니다. 언젠가 또 만나겠지만 말입니다. 행복은 지금 여기서 찾아야지 나중에 만나려고 하면 기다려주지 않습니다. :)  

 

마무리합니다. 아래 코드는 소숫점 둘째 자리까지 얻은 센서 값에 100을 곱해서 아랫자리를 자릅니다. 그래서 정수로 (int) 형 변환을 해주었습니다. 그리고 - 값이 나오는 것을 워낙 싫어해서 전부 절댓값 abs( ) 값으로 바꿔줍니다. 혹시 더 섬세한 배려와 예민한 검출을 원하신다면 곱하기 1,000을 해주시고, 값이 얼마나 변하는 지를 검사하시려면 절댓값으로 하시고 이전 값 - 지금 값 하시고 결과도 절댓값으로 하시면 더 배려하는 코드를 만드시게 됩니다. :)

 

아래 최종 코드는 센서 값을 대충 예민함을 가진 아이로 만들고, 정수로 만들고, 현재 값과 이전 값을 비교해서 x, y, z 값 모두 변하면 움직였다는 값을 증가시킵니다. 한 값이 주도적이라도 움직임은 세 축 모두 값이 변합니다. 

 

이상으로 마칩니다. 가을 단풍, 하늘, 바람처럼 아무리 아름다운 것들이 우리 앞에 있어도 보지 못하는 게 삶인가 봅니다. 행복하시고 누리시고 기억하고 가져가시고 가득 채우시길 바랍니다. :) 

 

/*
  Arduino LSM6DS3 - Simple Accelerometer

  This example reads the acceleration values from the LSM6DS3
  sensor and continuously prints them to the Serial Monitor
  or Serial Plotter.

  The circuit:
  - Arduino Uno WiFi Rev 2 or Arduino Nano 33 IoT

  created 10 Jul 2019
  by Riccardo Rizzo

  This example code is in the public domain.
*/

#include <Arduino_LSM6DS3.h>

float x, y, z;
int pre_x =0, pre_y = 0, pre_z = 0;
int movesense = 0;

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");

    while (1);
  }

  Serial.print("Accelerometer sample rate = ");
  Serial.print(IMU.accelerationSampleRate());
  Serial.println(" Hz");
  Serial.println();
  Serial.println("Acceleration in G's");
  Serial.println("X\tY\tZ");
}

void loop() {

  float x, y, z;
  int result_x, result_y, result_z;
  

  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);

    /*Serial.print(abs((int)(x*100)));
    Serial.print('\t');
    Serial.print(abs((int)(y*100)));
    Serial.print('\t');
    Serial.println(abs((int)(z*100)));*/

    result_x = abs((int)(x*100));
    result_y = abs((int)(y*100));
    result_z = abs((int)(z*100));

    Serial.print(result_x);
    Serial.print('\t');
    Serial.print(result_y);
    Serial.print('\t');
    Serial.println(result_z);

    if((result_x != pre_x) && (result_y != pre_y)&& (result_z != pre_z)) movesense++;

    pre_x = result_x;
    pre_y = result_y;
    pre_z = result_z;    

    Serial.println(movesense);  
  }
}

 

이렇게 해결함.  놀러 나가야지. ^^

 

색깔 곱다. 햇살, 바람, 빛, 나무 얼마나 좋은가.

 

 

 

 

반응형