하드웨어 평가에는 다음 소프트웨어가 사용됩니다.
- Audacity(PC에 설치됨)
- MATLAB (PC에 설치됨)
- 햅틱 테스트 앱 (DUT에 설치됨)
시스템 요구사항에 관한 자세한 내용은 Windows용 Audacity, Mac용 Audacity, MATLAB를 참고하세요.
Audacity 설정
특정 데이터 샘플링 레이트로 Sound Blaster 사운드 카드의 입력을 받으려면 대담을 설정해야 합니다. Sound Blaster를 컴퓨터의 USB 포트에 연결한 후 Audacity를 열고 다음 안내를 따르세요.
CCLD 출력을 Sound Blaster의 라인 입력 입력 포트에 물리적으로 연결하여 라인 (USB Sound Blaster HD)을 입력 마이크 소스로 선택합니다.
그림 1. 마이크 입력 선택 중
프로젝트 속도 메뉴에서 48000을 선택하여 샘플링 레이트를 48kHz로 설정합니다.
그림 2. 샘플링 레이트 설정
MATLAB 다운로드
MATLAB 파일을 다운로드합니다.
파일의 압축을 풀고
Effect1NEffect2_V1p0_2020PM.m
(Effect 1 및 Effect 2) 및Effect3_V1p0_2020PM.m
(Effect 3)을 찾습니다.
휴대전화에서 테스트 앱 설정
이 섹션에서는 휴대전화에서 테스트 앱을 설정하는 방법을 설명합니다.
테스트 앱 준비
- 아래 자바 및 Kotlin 코드 블록에서 소스 코드를 복사합니다. 가장 적합한 방법을 선택하세요.
- 그림 3에 표시된 GUI 매개변수에 따라 직접 코드를 작성합니다. 필요한 경우 레이아웃 소스 코드의 세부정보를 휴대전화와 일치하도록 조정합니다.
GUI에 클릭 가능한 버튼 3개와 가속도계를 찾을 영역을 정의하는 시각적 표시기가 포함되어 있는지 확인합니다.
- 가속도계를 찾을 영역은 일반적으로 손으로 터치하는 기기 화면의 실제 공간을 나타냅니다.
- 이 측정 중에 청록색 영역 내에서 가속도계를 움직여 가장 강한 신호를 캡처하는 화면 영역을 찾을 수 있습니다.
Android 기기에 코드를 설치합니다.
기본 모드가 버튼으로 설정된 경우 시스템 탐색 모드를 동작 모드로 설정하는 것이 좋습니다.
- 동작 모드를 설정하면 가속도계를 휴대전화의 시스템 탐색 GUI에 의해 중단되지 않으면서 휴대전화 하단에 최대한 배치할 수 있습니다.
Java 소스 코드
package com.example.hapticeffectassessment;
import static android.os.VibrationEffect.EFFECT_CLICK;
import android.graphics.Color;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private static final long oneShotTiming = 20;
private static final int oneShotAmplitude = 255;
private static final long[] waveformTimings = {500, 500};
private static final int[] waveformAmplitudes = {128, 255};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Vibrator vibrator = getSystemService(Vibrator.class);
// Click R.id.button1 button to generate Effect 1
findViewById(R.id.button1).setOnClickListener(
view -> vibrator.vibrate(VibrationEffect.createPredefined(EFFECT_CLICK)));
// Click R.id.button2 button to generate Effect 2
findViewById(R.id.button2).setOnClickListener(
view -> vibrator.vibrate(VibrationEffect.createOneShot(oneShotTiming, oneShotAmplitude)));
// Click R.id.button3 button to generate Effect 3
findViewById(R.id.button3).setOnClickListener(view -> {
vibrator.vibrate(VibrationEffect.createWaveform(waveformTimings, waveformAmplitudes, -1));
// See quick results of Effect 3
Button button = (Button) view;
if (vibrator.hasAmplitudeControl()) {
button.setText("Effect 3: PASS");
button.setBackgroundColor(Color.GREEN);
button.setTextColor(Color.BLACK);
} else {
button.setText("Effect 3: FAIL");
button.setBackgroundColor(Color.RED);
button.setTextColor(Color.WHITE);
}
});
}
}
Kotlin 소스 코드
package com.example.hapticeffectassessment
import android.graphics.Color
import android.os.Bundle
import android.os.VibrationEffect
import android.os.VibrationEffect.EFFECT_CLICK
import android.os.Vibrator
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivityKt : AppCompatActivity() {
private val oneShotTiming: Long = 20
private val oneShotAmplitude = 255
private val waveformTimings = longArrayOf(500, 500)
private val waveformAmplitudes = intArrayOf(128, 255)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val vibrator = getSystemService(Vibrator::class.java)
// Click button1 to generate Effect 1
button1.setOnClickListener {
vibrator.vibrate(VibrationEffect.createPredefined(EFFECT_CLICK))
}
// Click button2 to generate Effect 2
button2.setOnClickListener {
vibrator.vibrate(VibrationEffect.createOneShot(oneShotTiming, oneShotAmplitude))
}
// Click button3 to generate Effect 3
button3.setOnClickListener {
vibrator.vibrate(
VibrationEffect.createWaveform(waveformTimings, waveformAmplitudes, -1))
// See quick results of Effect 3
if (vibrator.hasAmplitudeControl()) {
button3.text = "Effect 3: PASS"
button3.setBackgroundColor(Color.GREEN)
button3.setTextColor(Color.BLACK)
} else {
button3.text = "Effect 3: FAIL"
button3.setBackgroundColor(Color.RED)
button3.setTextColor(Color.WHITE)
}
}
}
}
레이아웃 소스 코드 (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<Button
android:id="@+id/button1"
android:layout_width="350dp"
android:layout_height="60dp"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="32dp"
android:text="Effect 1"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="350dp"
android:layout_height="60dp"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="32dp"
android:text="Effect 2"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button1" />
<Button
android:id="@+id/button3"
android:layout_width="350dp"
android:layout_height="60dp"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="32dp"
android:text="Effect 3"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
<View
android:id="@+id/divider"
android:layout_width="363dp"
android:layout_height="1dp"
android:layout_marginStart="32dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="32dp"
android:background="?android:attr/listDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button3" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="363dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/bluebar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
그림 3. GUI에서 권장하는 영역을 따라 가속도계 연결