L'isteresi
è quella proprietà dei sistemi che li fa reagire con un certo
ritardo alle forze ad essi applicate. Ad esempio, all'atto di
sedersi su una poltrona imbottita, la relazione tra forza e
compressione del cuscino può essere di forma
isteretica, ed evidenza di ciò si può avere
dall'impronta lasciata nel momento in cui ci si rialza.
Nel design dell'interazione, l'isteresi viene introdotta
deliberatamente per ritardare le azioni del sistema rispetto
all'accadere di eventi. Per esempio, il click del mouse in una
certa area può attivare un menu, la cui scomparsa viene però
ritardata rispetto all'uscita da quella regione, in modo da
consentire all'utente di esplorare le voci del menu anche con
percorsi del mouse imperfetti.
Nei regolatori automatici, quale è ad esempio il termostato
per la regolazione di temperatura, è spesso presente un
elemento isteretico per evitare commutazioni spurie, ad
esempio dovute ai rimbalzi degli interruttori. Il
termostato, in particolare, attiva il bruciatore quando la
temperatura scende al di sotto di una soglia
(threshold) boolean acceso e due
soglie basso e alto:
if (acceso) {
if (signal < basso) {
// operazioni di spegnimento
acceso = false;
}
}
else //spento
if (signal > alto) {
// operazioni di accensione
acceso = true;
}
Exercise 1
Si scriva un programma Processing che disegni la curva della pressione acustica catturata dal microfono. A basse pressioni la curva sia disegnata in verde. Quando la pressione acustica supera una soglia superiore la curva deve diventare di colore rosso, e tornare ad essere verde quando torna al di sotto di una soglia inferiore.
Solution
Una soluzione che fa uso della libreria audio Minim è la seguente:
import ddf.minim.*;
AudioInput in;
int WIDTH=400, HEIGHT=200;
int x;
int level, prevLevel;
color colorLine=color(0,255,0);
boolean acceso=false;
int basso=80;
int alto=120;
Minim minim;
void setup()
{
size(WIDTH, HEIGHT);
minim = new Minim(this);
// get a line-in from Minim: mono, 512 sample buffer
// default sampling rate is 44100, default bit-depth is 16
in = minim.getLineIn(Minim.MONO, 512);
}
void draw()
{
if (x==0) {
background(0);
stroke(255,0,0); line(0,HEIGHT-alto,WIDTH,HEIGHT-alto);
stroke(0,255,0); line(0,HEIGHT-basso,WIDTH,HEIGHT-basso);
}
stroke(colorLine);
level = int(in.left.level()*HEIGHT*10);
line(x, HEIGHT - prevLevel, (x+1)%WIDTH, HEIGHT - level);
x = (x+1)%WIDTH;
prevLevel = level;
if (acceso) {
if (level < basso) {
colorLine = color(0, 255, 0);
acceso = false;
}
}
else //spento
{
if (level > alto) {
colorLine = color(255, 0, 0);
acceso = true;
}
}
}
void stop()
{
// always stop Minim
minim.stop();
super.stop();
}
Exercise 2
Si modifichi il codice di Exercise 1 in modo da ottenere la curva di livello di un noise gate. Quando il livello scende al di sotto della soglia verde, si applica uno smorzamento che gradualmente forza il segnale ad essere inudibile. Quando il livello supera la soglia rossa, si applica una amplificazione che riporta il segnale al livello originale.
Solution
Nella soluzione seguente il segnale viene abbattuto,
quando scende al di sotto della soglia inferiore,
mediante moltiplicazioni successive per un coefficiente
gDown, il cui valore (sempre minore di uno)
viene impostato in base al tempo desiderato di
smorzamento ed al frame rate. Lo smorzamento si
considera esaurito quando il segnale di ingresso viene
ad essere moltiplicato per gUp, di valore sempre maggiore di uno.
import ddf.minim.*;
AudioInput in;
int WIDTH=400, HEIGHT=200;
int x;
int level, prevLevel, levelG;
color colorLine=color(0,255,0);
boolean acceso=false;
int basso=30;
int alto=50;
float damp=1.0;
float gain = 1.0;
Minim minim;
float decayTime = 10.0; // in seconds
float raiseTime = 2.0;
float gDown = pow(10,-2/frameRate/decayTime);
float gUp = pow(10,2/frameRate/raiseTime);
void setup()
{
println("gDown = " + gDown + "gUp = " + gUp);
size(WIDTH, HEIGHT);
minim = new Minim(this);
// get a line-in from Minim: mono, 512 sample buffer
// default sampling rate is 44100, default bit-depth is 16
in = minim.getLineIn(Minim.MONO, 512);
}
void draw()
{
if (x==0) {
background(0);
stroke(255,0,0); line(0,HEIGHT-alto,WIDTH,HEIGHT-alto);
stroke(0,255,0); line(0,HEIGHT-basso,WIDTH,HEIGHT-basso);
}
stroke(colorLine);
level = int(in.left.level()*HEIGHT);
gain = gain*damp;
//println(gain);
if (gain > 1.0) gain = 1.0;
if (gain < 0.01) gain = 0.01;
levelG = int(level*gain);
line(x, HEIGHT - prevLevel, (x+1)%WIDTH, HEIGHT - levelG);
x = (x+1)%WIDTH;
prevLevel = levelG;
if (acceso) {
if (level < basso) {
colorLine = color(0, 255, 0);
damp = gDown;
acceso = false;
}
}
else //spento
{
if (level > alto) {
colorLine = color(255, 0, 0);
damp = gUp;
acceso = true;
}
}
}
void stop()
{
// always stop Minim
minim.stop();
super.stop();
}
Gli esempi di sogliatura, isteresi, e gating visti nel caso dell'elaborazione del segnale audio sono di utilità generale per qualsiasi flusso di segnale proveniente da un sensore e, in particolare, anche nell'elaborazione di segnale video.




