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 |
SensorMagnetic.7z