הגדרת תוכנת הבדיקה

התוכנות הבאות משמשות לבדיקת החומרה:

  • Audacity (מותקן במחשב)
  • MATLAB (מותקן במחשב)
  • אפליקציית בדיקת מגע בהטיה (מותקנת ב-DUT)

מידע נוסף על דרישות המערכת זמין במאמרים בנושא Audacity ל-Windows, Audacity ל-Mac ו-MATLAB.

הגדרת Audacity

צריך להגדיר את Audacity כך שיקבל קלט מכרטיס האודיו Sound Blaster בתדירות דגימה מסוימת של נתונים. אחרי שמחברים את Sound Blaster ליציאת ה-USB של המחשב, פותחים את Audacity ופועלים לפי ההוראות הבאות.

  1. בוחרים באפשרות Line (USB Sound Blaster HD) כמקור המיקרופון להזנת האות, על ידי חיבור פיזי של יציאת ה-CCLD לשקע הקלט Line In של Sound Blaster.

    קלט מיקרופון

    איור 1. בחירת קלט מיקרופון

  2. מגדירים את תדירות הדגימה ל-48kHz על ידי בחירה באפשרות 48000 בתפריט Project Rate.

    תדירות הדגימה

    איור 2. הגדרת תדירות הדגימה

הורדת MATLAB

  1. מורידים את קובץ MATLAB.

  2. מחלצים את הקובץ ומחפשים את Effect1NEffect2_V1p0_2020PM.m (לאפקט 1 ולאפקט 2) ואת Effect3_V1p0_2020PM.m (לאפקט 3).

הגדרת אפליקציית הבדיקה בטלפון

בקטע הזה נסביר איך מגדירים את אפליקציית הבדיקה בטלפון.

הכנה לקראת אפליקציית הבדיקה

  1. מעתיקים את קוד המקור מקטע הקוד של Java ומקטע הקוד של Kotlin שבהמשך. אפשר לבחור את האפשרות שמתאימה לך.
  2. כותבים קוד משלכם בהתאם לפרמטרים של ממשק המשתמש הגרפי שמוצגים באיור 3. אם צריך, משנים את הפרטים של קוד המקור של הפריסה כך שיתאים לטלפון.
  3. חשוב לוודא ש-GUI כולל שלושה לחצנים שניתן ללחוץ עליהם ואינדיקטור חזותי כדי להגדיר את האזור שבו ימוקם מד התאוצה.

    • האזור שבו מאתרים את ה-accelerometer מייצג את שטח המסך של המכשיר שנוגעים בו בדרך כלל ביד.
    • במהלך המדידה, אפשר להזיז את ה-accelerometer באזור התכלת כדי למצוא את אזור המסך שמקבל את האות החזק ביותר.
  4. מתקינים את הקוד במכשיר Android.

  5. מומלץ מאוד להגדיר את מצב הניווט במערכת למצב תנועות אם מצב ברירת המחדל מוגדר כלחצנים.

    • הגדרת מצב התנועות מאפשרת להציב את ה-accelerometer בחלק התחתון של הטלפון ככל האפשר, בלי הפרעה מממשקי המשתמש הגרפיים של ניווט המערכת בטלפון.

קוד מקור של 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. מחברים את ה-accelerometer באזור המומלץ בממשק המשתמש