gbm
Sensore distanza LED analogico
Tutorials -
Lunedì 16 Gennaio 2012 00:00
Scritto da gbm

Come ben saprete, questi componenti si comportano come fotodiodi o celle solari, producendo una tensione proporzionale all'intensità luminosa che colpisce la giunzione.

Con un tester, un LED e il sole o qualsiasi altra fonte luminosa è possibile divertirsi osservando la fluttuazione della tensione in relazione alla luce solare.

Dopo il test empirico, scommetto avrete gia 2 o 3 applicazioni pratiche in testa. Io mi sono dedicato ad alcuni progetti che si basano su questo principio come la Comunicazione bidirezionale a LED, iil Sensore di colore LED e LED utilizzato come cella solare o sensore di luce.

 

Con questo tutorial vedremo come costruire un sensore di distanza con solo due LED di qualsiasi tipo o genere (consigliati infrarossi o blu con adeguata schematura) con un range di 5 metri. Cosa incredibile, avremo un output lineare e quindi scalabile a qualsiasi unità di misura metrica. Regolando la quantità di letture sarà possibile scegliere il tempo di esposizione e quindi la durata di ogni acquisizione.

Non è cosi' incredibile come sembra ;)

 

L'applicazione dell'algoritmo ERER

Questo sistema permette di determinare l'intensità di luce riflessa da una superficie posta davanti al sensore. Per farlo il sensore effettua due letture, una a emettitore acceso e una a emettitore spento. Sottraendo all'intensità ottenuta a emettitore acceso l'intensità ambientale, otterremo un valore che rappresenta esattamente la luce riflessa perfettamente filtrata dalla componente ambientale. Con nostro grande piacere la comunità ha recepito in modo molto positivo il nostro lavoro anche all'estero, vista la sua semplicità e costo ridotto.

 

Dall'intensità alla distanza

Grazie al filtraggio ERER otteniamo l'intensità luminosa del riflesso ottenuto. Questo valore non ha un comportamento lineare ma piuttosto iperbolico, rispettando la Invese square law o Legge dell'inverso del quadrato della distanza. Questa legge fisica mi ha davvero entusiasmato perchè se capita davvero, permette di conoscere molto meglio l'universo che ci circonda a livello fisico matematico, pensate che i conti  tornano con il suono, la luce, campi elettromagnetici e gravitazionali. E' stata enormemente utilizzata in campo fisico e astronomico per conoscere la distanza di corpi spaziali, analizzando proprio l'intensità di essi. Io la utilizzo per rendere lineare un input che è inversamente proporzionale al quadrato della distanza e di conseguenza iperbolico.

 

Sempre grazie alla inverse square law, conoscendo un valore di intensità percepita correlato a una distanza nota è possibile determinare, conoscendo solo l'intensità, la distanza della fonte luminosa.

legge dell'inverso del quadrato della distanza

Vediamo l'equazione:

Intensità = Potenza / 4 * pigreco * distanza ²

InverseSquareLaw

Sfruttiamo come misura nota la distanza minima percepita dal sensore:

distanza attuale = sqrt( intensità a contatto / intensità attuale )

Legge dell'inverso del quadrato della distanza    Iperbole intensità luminosa
Questa rappresentazione grafica chiarisce la natura iperbolica.    Ed ecco la forma del nostro input prima di essere stato linearizzato

 

Questa equazione linearizza l'output della nostra funzione e rende il valore ottenuto una distanza lineare scalabile in un qualsiasi valore metrico, permettendo la percezione della distanza in mm per oltre 5 metri di range effettivo con un rate di 30 rilevazioni al secondo ;). Questo sistema ovviamente è limitato dall'ADC a bassa risoluzione di Arduino, e dalla variabile in cui salviamo il dato ottenuto, in questo caso un double. 

 

L'integrazione della tensione

Dopo alcuni test e ricerche, sono giunto alla conclusione che, integrando la tensione nel tempo, avrei ottenuto un valore molto piu' grande e una risoluzione maggiore, a discapito ovviamente della velocità di refresh del valore. Di conseguenza ho scelto di mediare e ottenere un range di 5m in situazione indoor o notturna con un rate di 30 letture al secondo. Regolando la variabile readings è possibile settare il sensore per perepire una distanza breve in modo estremamente  veloce, oppure una distanza maggiore con un rate piu' elevato. 

 

Le variabili in gioco

Scrivere un software che permetta una misurazione della distanza in modo preciso, lavorando in un ambiente cosi' pieno di disturbo e potendo rilevare oggetti con riflettività molto differenti è molto complesso. Quello che ci aiuta è sicuramente la possibilità di poter conoscere la luce ambientale o radiazione di fondo. La riflettività dell'ostacolo è ignota, quindi la sua distanza non è perfettamente determinabile in un punto, ma in una serie di punti.

 

Luce ambientale - La radiazione luminosa prodotta da lampadine a incandescenza o alogene (che contiene una forte componente infrarossa), riduce il range del nostro sensore. L'esperimento piu' pratico è la prova dell'accendino cioè stampare in seriale la distanza ottenuta e accendere e spegnere l'accendino. Quando questo sarà acceso il nostro sensore sentirà la superficie riflettente piu' distante e viceversa.

 

Riflettività superficie - Una possibile imprecisione del dato ottenuto è dato dalla riflettività di una superficie. Per ovvi motivi, uno specchio sarà percepito piu' vicino di una sedia in pelle nera. Per fortuna anche grazie (o per colpa) della legge fisica esposta precedentemente questo drift incide solo per al massimo il 10% con l'algoritmo da noi utilizzato.

 

Il codice

Come potete vedere ho cercato di rendere il codice piu' pulito e facilmente leggibile. In questo caso, per comodità vengono utilizzate le porte analogiche 1 e 2 per alimentare e predisporre la massa per l'emettitore, ovviamente è possibile modificare il numero della porta in modo da non sprecare una analogica e utilizzare una sola porta digitale per pilotarlo. La variabile readings contiene la quantità di letture analogiche che effettuera' il sensore. FIlterValue invece è una variabile che permette l'uso di un filtro molto interessante che mi ha mostrato Martino. Questo filterValue, viene moltiplicato al valore di distanza precedente, contemporaneamente viene moltiplicato 1 - filterValue al valore di distanza attuale, cosi' da fare una sorta di media pesata tra gli ultimi due valori ottenuti, dando piu' importanza e tenendo in considerazione maggiormente il primo valore. Questo permette di avere un output decisamente piu' smooth e utilizzabile.

// SENSORE ERER DISTANZA E LUCE AMBIENTALE CON LED INFRAROSSI
// ALGORITMO ERER E INVERSE SQUARE LAW 
// IDEATO DA GIOVANNI BLU MITOLO 2012
// WWW.GIOBLU.COM
// LED based analog distance sensor by Giovanni Blu Mitolo 
//is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 

int inputPIN = A0;               // PIN LED RICEVITORE
int emitterPIN = A1;             // PIN LED EMETTITORE
double minDistanceIntensity = 0; // MASSIMA INTENSITA' RILEVATA
double intensity = 0;            // INTENSITA'
double distance = 0;             // DISTANZA
double reading = 0;              // LETTURA ATTUALE
double ambient = 0;              // LETTURA AMBIENTALE
int readings = 2000;             // COSTANTE NUMERO LETTURE 
int filterValue = 0.1;           // COSTANTE GAIN DEL FILTRO

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 
// SET PRESCALE PORTE ANALOGICHE

void setup() { 
  pinMode(inputPIN, INPUT); 
  pinMode(emitterPIN, OUTPUT); 
  pinMode(A2, OUTPUT); 
  Serial.begin(115200); 
  // setta  prescale a 32 
  // riduci la durata della lettura analogica da 128 micros (standard) a 32
  sbi(ADCSRA,ADPS2); 
  cbi(ADCSRA,ADPS1); 
  sbi(ADCSRA,ADPS0); 
} 

void getDistance() { 
  ambient = 0; 
  intensity = 0; 
  digitalWrite(emitterPIN, LOW); // Lettura ambientale 
  for(int i = 0; i < readings; i++) { 
    ambient = ambient + analogRead(inputPIN); 
  } 
  digitalWrite(emitterPIN, HIGH); // Lettura attiva 
  for (int i = 0; i < readings; i++) { 
    intensity = intensity + analogRead(inputPIN); 
  } 
  digitalWrite(emitterPIN, LOW);
  if(ambient < intensity) intensity = intensity - ambient; // Filtro luce ambientale 
    if(intensity > minDistanceIntensity) minDistanceIntensity = intensity; // Salva l'intensità maggiore percepita 
    distance = (distance * filterValue) + (sqrt(minDistanceIntensity / intensity) * (1 - filterValue)); 
} 

void loop() { 
  long time = millis();
  getDistance();
  Serial.print(1000 / (millis() - time));
  Serial.print(" ");
  Serial.print(distance);
  Serial.print(" ");
  Serial.print(intensity); 
  Serial.print(" ");
  Serial.println(intensity / ambient);
} 

Il sensore ha un sistema adattivo, che necessita di percepire la distanza minima prima di iniziare a funzionare correttamente, quindi prima di iniziare i test, dopo aver caricato il codice, posizionate il sensore a contatto con un qualsiasi oscatolo o piu' semplicemente il vostro dito. Riepilogando stimo che il valore di distanza possa contenere un errore medio del 20% in rapporto a riflettività e illuminazione ambientale. Il che a 60 cm puo' generare un valore di distanza errato di al massimo 12/15cm.

Tutto questo è pensato per ottenere un sensore versatile. Sarà possibile effetturare poche letture e avere rate spaventosi, ma range ridotti, cosa molto utile nei line follower, ma anche range molto lunghi per ottenere una fotografia di una stanza con range maggiori di 5 metri grazie a un sistema di tilt pan come Image Scanner. Quindi, se avete bisogno di un sensore per il vostro robot, sconsiglio i sensori Sharp, a fronte di una sperimentazione di questo algoritmo e l'acquisto / riciclo di due semplici LED, possibilmente a infrarossi. E' possibile usare anche LED colorati, con risultati meno soddisfacenti.


Creative Commons License LED based analog distance sensor by Giovanni Blu Mitolo is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. Based on a work at www.gioblu.com.
 

Gioblu Robotics © 2010 - 2012 · Sitemap · privacy

gioscarab@gmail.com

Gioblu BOTServer è online dal 10 Aprile 2010 - 319.232 Visite - 1.027.175 Pagine visualizzate - 182.309 Visitatori unici - 536 utenti attivi