Analizzare le forme d'onda delle vibrazioni

Gli attuatori di vibrazione più comuni sui dispositivi Android sono gli attuatori risonanti lineari (LRA). Gli LRA simulano la sensazione di un clic su un pulsante su una superficie di vetro altrimenti non reattiva. Un segnale di feedback di clic chiaro e nitido dura in genere tra 10 e 20 millisecondi. Questa sensazione rende le interazioni dell'utente più naturali. Per le tastiere virtuali, questo feedback di clic può aumentare la velocità di digitazione e ridurre gli errori.

Gli LRA hanno alcune frequenze di risonanza comuni:

  • Alcuni LRA avevano frequenze di risonanza nell'intervallo da 200 a 300 Hz, che coincide con la frequenza alla quale la pelle umana è più sensibile alle vibrazioni. La sensazione delle vibrazioni in questo intervallo di frequenza viene solitamente descritta come fluida, nitida e penetrante.
  • Altri modelli di LRA hanno frequenze di risonanza inferiori, intorno ai 150 Hz. La sensazione è qualitativamente più morbida e piena (in termini di dimensioni).
I componenti includono, dall'alto verso il basso, una copertura, una piastra, un magnete centrale, due magneti laterali, una massa, due molle, una bobina, un circuito flessibile, una base e un adesivo.
Componenti di un attuatore risonante lineare (LRA).

A parità di tensione di ingresso a due frequenze diverse, le ampiezze dell'uscita di vibrazione possono essere diverse. Più la frequenza è lontana dalla frequenza di risonanza dell'LRA, minore è l'ampiezza della vibrazione.

Gli effetti aptici di un determinato dispositivo utilizzano sia l'attuatore di vibrazione sia il relativo driver. I driver aptici che includono le funzionalità di overdrive e frenata attiva possono ridurre il tempo di salita e il ringing degli LRA, con conseguente vibrazione più reattiva e chiara.

Accelerazione dell'uscita del vibratore

Il mapping frequenza-accelerazione di uscita (FOAM) descrive l'accelerazione di uscita massima raggiungibile (in G di picco) a una determinata frequenza di vibrazione (in Hertz). A partire da Android 16 (livello API 36), la piattaforma fornisce il supporto integrato per questo mapping tramite VibratorFrequencyProfile. Puoi utilizzare questa classe, insieme alle API di inviluppo di base e avanzate, per creare effetti aptici.

La maggior parte dei motori LRA ha un singolo picco nel FOAM, in genere vicino alla frequenza di risonanza. In genere, l'accelerazione diminuisce in modo esponenziale man mano che la frequenza si discosta da questo intervallo. La curva potrebbe non essere simmetrica e potrebbe presentare un plateau intorno alla frequenza di risonanza per proteggere il motore da eventuali danni.

Il grafico adiacente mostra un esempio di FOAM per un motore LRA.

Man mano che la frequenza aumenta fino a circa 120 Hz, l'accelerazione aumenta
       in modo esponenziale. L'accelerazione rimane costante fino a circa 180 Hz,
       dopodiché diminuisce.
Esempio di FOAM per un motore LRA.

Soglia di rilevamento della percezione umana

La soglia di rilevamento della percezione umana si riferisce all'accelerazione minima di una vibrazione che una persona può rilevare in modo affidabile. Questo livello varia in base alla frequenza di vibrazione.

Il grafico adiacente mostra la soglia di rilevamento della percezione aptica umana, in termini di accelerazione, in funzione della frequenza temporale. I dati della soglia vengono convertiti dalla soglia di spostamento nella Figura 1 dell'articolo di Bolanowski Jr., S. J., et al. del 1988, "Four channels mediate the mechanical aspects of touch.".

Android gestisce automaticamente questa soglia in BasicEnvelopeBuilder, che verifica che tutti gli effetti utilizzino un intervallo di frequenza che produca ampiezze di vibrazione che superino la soglia di rilevamento della percezione umana di almeno 10 dB.

Man mano che la frequenza aumenta fino a circa 20 Hz, la soglia di rilevamento umano
       aumenta in modo logaritmico fino a circa -35 dB. La soglia rimane costante
       fino a circa 200 Hz, dopodiché aumenta in modo approssimativamente lineare fino a
       -20 dB.
Soglia di rilevamento della percezione aptica umana.

Un tutorial online spiega ulteriormente la conversione tra l'ampiezza dell'accelerazione e l'ampiezza dello spostamento.

Livelli di accelerazione della vibrazione

La percezione umana dell'intensità della vibrazione, una misura di percezione, non cresce in modo lineare con l'ampiezza della vibrazione, un parametro fisico. L'intensità percepita è caratterizzata dal livello di sensazione (SL), definito come una quantità di dB sopra la soglia di rilevamento alla stessa frequenza.

L'ampiezza dell'accelerazione della vibrazione corrispondente (in G di picco) può essere calcolata come segue:

$$ Amplitude(G) = 10^{Amplitude(db)/20} $$

...dove l'ampiezza in dB è la somma di SL e della soglia di rilevamento, ovvero il valore lungo l'asse verticale nel grafico adiacente, a una determinata frequenza.

Il grafico adiacente mostra i livelli di accelerazione della vibrazione a 10, 20, 30, 40 e 50 dB SL, insieme alla soglia di rilevamento della percezione aptica umana (0 dB SL), in funzione della frequenza temporale. I dati sono stimati dalla Figura 8 dell'articolo di Verrillo, R. T., et al. del 1969, "Sensation magnitude of vibrotactile stimuli.".

Man mano che il livello di sensazione desiderato aumenta, l'accelerazione richiesta,
       in dB, aumenta di circa la stessa quantità. Ad esempio, il livello di sensazione di 10 dB per una vibrazione di 100 Hz è di circa -20 dB, anziché -30 dB.
Livelli di accelerazione della vibrazione.

Android gestisce automaticamente questa conversione in BasicEnvelopeBuilder, che accetta i valori come intensità normalizzate nello spazio del livello di sensazione (dB SL) e li converte in accelerazione di uscita. WaveformEnvelopeBuilder, d'altra parte, non applica questa conversione e accetta invece i valori come ampiezze di accelerazione di uscita normalizzate nello spazio di accelerazione (Gs). L'API di inviluppo presuppone che, quando un progettista o uno sviluppatore pensa alle modifiche della forza di vibrazione, si aspetti che l'intensità percepita segua un inviluppo lineare a tratti.

Smoothing predefinito della forma d'onda sui dispositivi

A titolo illustrativo, considera il comportamento di un pattern di forma d'onda personalizzato su un dispositivo generico:

Kotlin

val timings: LongArray = longArrayOf(50, 50, 50, 50, 50, 100, 350, 250)
val amplitudes: IntArray = intArrayOf(77, 79, 84, 99, 143, 255, 0, 255)
val repeatIndex = -1 // Don't repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))

Java

long[] timings = new long[] { 50, 50, 50, 50, 50, 100, 350, 250 };
int[] amplitudes = new int[] { 77, 79, 84, 99, 143, 255, 0, 255 };
int repeatIndex = -1 // Don't repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));

I seguenti grafici mostrano la forma d'onda di input e l'accelerazione di uscita corrispondenti agli snippet di codice precedenti. Tieni presente che l'accelerazione aumenta gradualmente, non improvvisamente, ogni volta che si verifica una variazione graduale dell'ampiezza nel pattern, ovvero a 0 ms, 150 ms, 200 ms, 250 ms e 700 ms. Si verifica anche un overshoot a ogni variazione graduale dell'ampiezza e si verifica un ringing visibile che dura almeno 50 ms quando l'ampiezza di input scende improvvisamente a 0.

Grafico della forma d'onda di input della funzione a gradini.
Grafico della forma d'onda misurata effettiva, che mostra transizioni più organiche tra i livelli.

Pattern aptico migliorato

Per evitare l'overshoot e ridurre il tempo di ringing, modifica le ampiezze in modo più graduale. Di seguito sono riportati i grafici della forma d'onda e dell'accelerazione della versione rivista:

Kotlin

val timings: LongArray = longArrayOf(
    25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,
    300, 25, 25, 150, 25, 25, 25
)
val amplitudes: IntArray = intArrayOf(
    38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,
    0, 85, 170, 255, 170, 85, 0
)
val repeatIndex = -1 // Do not repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))

Java

long[] timings = new long[] {
        25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,
        300, 25, 25, 150, 25, 25, 25
    };
int[] amplitudes = new int[] {
        38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,
        0, 85, 170, 255, 170, 85, 0
    };
int repeatIndex = -1; // Do not repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));

Grafico della forma d'onda di input con passaggi aggiuntivi.
Grafico della forma d'onda misurata, che mostra transizioni più fluide.

Creare effetti aptici più complessi

Altri elementi di una risposta di clic soddisfacente sono più complessi e richiedono una certa conoscenza dell'LRA utilizzato in un dispositivo. Per risultati ottimali, utilizza le forme d'onda prefabbricate del dispositivo e le costanti fornite dalla piattaforma, che ti consentono di:

  • Eseguire effetti e primitive chiari.
  • Concatenarli per comporre nuovi effetti aptici.

Queste costanti e primitive aptiche predefinite possono velocizzare notevolmente il tuo lavoro durante la creazione di effetti aptici di alta qualità.