TYPE_MAGNETIC_FIELD는 지구 자기장의 강도를 수치로
보여주는 센서로 주변 금속의 강도에 따라 맴돌이 전류가 발생하여
자기장이 영향을 받는 것을 이용해 간단한 금속탐지기 기능을 구현해 봅니다.
지자기장은 지구의 위치마다 달라 20~80정도로 차이가 발생하고 한국은 50정도 입니다.
좀더 성능 좋은 금속탐지기를 만들려면 TYPE_MAGNETIC_FIELD_UNCALIBRATED 센서를 이용해서원래의 값을 받아와 보정 작업을 진행해야 합니다.
1 자기장 센서
1.1 자기장 센서 이벤트 값
TYPE_MAGNETIC_FIELD 센서가 작동 되면 리턴되는 값으로 다음과 같은 value를 넘겨 주며 단위는 μT(마이크로 테슬라)입니다.
리턴된 값은 센서에서 보내주는 값들을 자체 보정 해서 나온 수치 입니다.
Sensor |
Sensor event data |
표현 값 |
측정 단위 |
TYPE_MAGNETIC_FIELD |
SensorEvent.values[0] |
x축 지구자장 강도 |
μT |
TYPE_MAGNETIC_FIELD |
SensorEvent.values[1] |
y축 지구자장 강도 |
μT |
TYPE_MAGNETIC_FIELD |
SensorEvent.values[2] |
z축 지구자장 강도 |
μT |
2 자기장 센서 프로젝트
2.1 신규 프로젝트 생성
안드로이드 스튜디오에서 적당한 이름으로 프로젝트를 하나 생성합니다.
2.2 Layout 작성
activity_main.xml
자기장 센서가 보내오는 x, y, z축의 μT값들을 출력할 수 있는 TextView를 작성합니다.
그리고 간략한 금속 탐지 기능을 보여줄 TextView도 하나 생성 합니다.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Megnetic Value" android:layout_marginTop="50dp" android:textSize="30dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tvXaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvTitle" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="X axis : 0" /> <TextView android:id="@+id/tvYaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvXaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Y axis : 0" /> <TextView android:id="@+id/tvZaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvYaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Z axis : 0" /> <TextView android:id="@+id/tvMagnetic" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvZaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Magnetic : 0" /> </android.support.constraint.ConstraintLayout>
2.3 Java Source
MainActivity.java
소스를 보면 알겠지만 기존 센서와 동일한 프로세스로 작동이 됩니다.
자세한 설명은 생략 합니다. 기존 센서 예제를 확인 하세요.
onCreate에서 Sensor.TYPE_MAGNETIC_FIELD를 설정 하고 onSensorChanged에서 x, y, z 축의 magnetic 값을 받아와 출력 합니다.
지자기 총량을 구하는 공식은
Math.sqrt((magX * magX) + (magY * magY) + (magZ * magZ))
입니다.
package com.example.desk.sensormagnetic; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements SensorEventListener { private SensorManager sensorManager; private Sensor magSensor; int rotation; TextView tvXaxis, tvYaxis, tvZaxis, tvMagnetic; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvXaxis = (TextView)findViewById(R.id.tvXaxis); tvYaxis = (TextView)findViewById(R.id.tvYaxis); tvZaxis = (TextView)findViewById(R.id.tvZaxis); tvMagnetic = (TextView)findViewById(R.id.tvMagnetic); sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); magSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); } @Override protected void onResume() { super.onResume(); sensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent event) { if(event.sensor ==magSensor) { float magX = event.values[0]; float magY = event.values[1]; float magZ = event.values[2]; double magnitude = Math.sqrt((magX * magX) + (magY * magY) + (magZ * magZ)); tvXaxis.setText("X axis : " + String.format("%.2f", magX)); tvYaxis.setText("Y axis : " + String.format("%.2f", magY)); tvZaxis.setText("Z axis : " + String.format("%.2f", magZ)); tvMagnetic.setText("Magnetic : " + String.format("%.2f", magnitude) + " \u00B5Tesla"); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }
µ를 나타내기 위해 사용한 u00B5는
유니코드입니다.
인터넷에서 유니코드를 검색하면 표로 잘 나와있어서 앞자리+윗자리 숫자를 조합해서 사용하면 됩니다.
위키 백과사전에서 조금 뜯어왔습니다.
3. 결과
3.1 결과 화면
프로젝트를 실제 핸드폰에서 테스트한 결과 화면인데요.
책상 위에 놓았을 때 하고 컴퓨터 위에 놓았을 때의 값을 비교해보고
책상 위에서 자석을 위치 했을 때의 값을 비교해 보았습니다.
방구석에 처박혀 있을 때 켜놓고 이리저리 굴러다니며 테스트하면 나름 재미있습니다.
3.2 Source Code
3.3 APK File
- copy coding -
'Android' 카테고리의 다른 글
안드로이드 중력 센서 (TYPE_GRAVITY) (0) | 2018.10.13 |
---|---|
안드로이드 가속도 센서 비교 (TYPE_ACCELEROMETER/TYPE_LINEAR_ACCELERATION) (2) | 2018.10.13 |
안드로이드 장치의 회전 방향 확인 (TYPE_GYROSCOPE) (0) | 2018.10.01 |
안드로이드 광 센서 테스트 (TYPE_LIGHT) (0) | 2018.09.27 |
안드로이드 핸드폰 센서 비교 (TYPE_STEP_DETECTOR 와 TYPE_STEP_COUNTER) (2) | 2018.09.15 |