ublo
bogdan's (micro)blog

bogdan » arduino: senzor de lumină cu led

11:20 am on Mar 25, 2018 | #more | tags:

în urma rugăminții profesorului Stamatin, de câțiva ani țin un curs la Facultatea de Fizică din Măgurele. dacă inițial numele «modelare și simulare» ascundea ecuații matematice și metode numerice, recent am înlocuit diferențialele cu Arduino, în ovațiile celor câtorva studenți care frecventează cursul. dotările limitate m-au făcut să devin creativ cu materialele de curs, iar rezultatul mi s-a părut suficient de interesant pentru a-l reproduce aici. așa că:

senzorii de lumină domină lumea simțurilor electronice. cu mici modificări, aceștia pot răspunde unei multitudini de întrebări, de la banalul ”e lumină afară?”, la ”ce culoare are un obiect?” sau ”la ce distanță am un obstacol în față?”. la prima vedere funcționează complex: un fragment de siliciu reacționează la lumina incidentă, modificând o mărime electrică. Einstein a luat premiul Nobel pentru explicarea principiului în 1921, deci trebuie să fie complicat. cu toate acestea, tehnologia s-a dezvoltat pe parcursul secolului care a trecut suficient de mult ca să putem reface experimentul în bucătărie.

materiale necesare:

  • un Ardunio, de orice fel, în funcție de cât de familiarizat ești cu el; la curs l-am folosit pe ăsta (31 de lei);
  • un led obișnuit, orice culoare și orice mărime, dar să fie un led simplu; știi că e un led simplu (30 de bani), dacă e foarte ieftin;
  • două fire pentru a lega ledul la Arduino; mie îmi plac astea (3 lei), dar pot fi de orice fel;

puțină teorie:
un led este un dispozitiv semiconductor, de obicei din siliciu, al cărui element activ este vizibil. elementul activ poartă numele de joncțiune, adică locul de întâlnire pentru două materiale cu proprietăți diferite. ce e important de reținut pentru construcția de față este că cele două materiale formează un sandviș cu un mic spațiu între ele, asemeni unui condensator de la fizică. în funcționarea normală, trecerea curentului electric prin acel mic spațiu produce lumină. cu siguranță ai observat că polaritatea e importantă, deoarece lumina și circulația curentului se produc doar într-un singur sens.

ce se întâmplă în schimb când polaritatea e inversată? lipsa curentului electric duce la acumularea de sarcini electrice pe fețele sandvișului, încărcând condensatorul. cum naturii îi plac simetriile, orice rază de lumină incidentă generează perechi de sarcini, care se vor deplasa în direcții opuse, datorită atracției electrostatice. ajunse pe suprafețele sandvișului, acestea vor scădea sarcina acumulată pe condensator, scăzând proporțional și tensiunea electrică.

în mod normal, procesele se întâmplă extrem de repede și sunt extrem de mici ca intensitate. dar aici intervine genialitatea oamenilor care au proiectat Arduino: acesta e suficient de rapid și suficient de sensibil pentru a face față experimentului.

ce se va întâmpla:
Arduino va încărca ledul, alimentându-l invers, după care va număra cât îi ia condesatorului format în jurul joncțiunii ledului pentru a se descărca. pentru a repeta experimentul de la curs, vei conecta ledul cu plusul (piciorușul mai lung, anodul) la GND (ground, 0V) și minusul (piciorușul mai scurt, catodul) la unul dintre terminalele Arduino, cu excepția pinilor 0,1 - care sunt responsabili pentru comunicarea serială și pinul 13, care are deja un led conectat intern și care te va încurca. eu am ales pinul 2.

în pregătirea Arduino, am definit un loc în memorie pentru stocarea informațiilor primite de la led. tipul de date folosit va fi întreg (int), numărând câte perioade de timp condensatorul a fost încărcat. pentru a fi accesibilă de oriunde, definiția se va afla în afara și înaintea celor două funcții speciale Arduino, setup și loop.

int value; // <- asa definesc un loc in memorie, int este tipul, iar value este numele
// pentru ca am definit-o în afara setup și loop, voi putea să o accesez de oriunde, prin nume
void setup() {}
void loop() {}

pentru citirea informațiilor, am folosit interfața serială a Arduino, care va fi inițializată prin:

int value;
void setup() {
  Serial.begin(9600); // <- aici initializez conexiunea seriala cu viteza de 9600 caractere / s
}
void loop() {}

periodic, am încărcat ledul pentru un interval de timp. experimental am ales 1ms.

int value;
void setup() {
  Serial.begin(9600);
}
void loop() {
  pinMode(2, OUTPUT); // <- aici definesc pinul 2 ca fiind pin de iesire
  digitalWrite(2, HIGH); // <- setez tensiunea pe pinul 2 la tensiunea de alimentare a Arduino
  delay(1); // <- astept 1ms, sa incarc condensatorul ledului
}

am măsurat în cât timp tensiunea la bornele ledului scade sub un anumit prag. aici aș fi putut să folosesc convertorul analog-digital din Arduino, dar în unele situații este prea lent. așa că am folosit proprietatea unui pin digital configurat ca intrare de a-și schimba starea în jurul jumătății tensiunii de alimentare a Arduino. astfel, dacă tensiunea la intrare scade sub 2.5V față de GND (pentru un Arduino alimentat la 5V), valoarea citită intern va fi LOW, în timp ce dacă tensiunea crește peste 2.5V, valoarea citită va fi HIGH.

pentru a determina în cât timp tensiunea la bornele ledului scade, am verificat la intervale scurte de timp dacă a scăzut. dacă a scăzut, trimit prin conexiunea serială valoarea înregistrată, altfel, mai aștept puțin timp și verific din nou. experimentând, am folosit ca timp de așteptare 40uS.

int value;
void setup() {
  Serial.begin(9600);
}
void loop() {
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  delay(1);
  pinMode(2, INPUT);
  value = 0; // <- aici resetez ce stochez în memorie
  while(digitalRead(2) == HIGH) { // <- citesc pinul 2 si verific daca tensiunea depasește pragul
    delayMicroseconds(40); // <- daca e peste prag, lumina e prea slabă și aștept 40uS
    value = value + 1; // <- cresc cu o unitate valoarea stocată
  }
  // <- aici tensiunea la bornele ledului a scazut sub prag
  Serial.println(value); // <- așa că trimit valoarea prin conexiunea serială
}

în funcție de led și de condițiile de iluminare, valorile primite de calculator sunt uneori negative. acest lucru se întâmplă deoarece numărul de repetări depășește valoarea maximă care poate fi stocată într-un segment de memorie de tip întreg. pentru a preveni această situație, am introdus o limitare la 255 a numărului de cicluri pentru care verificarea are loc:

int value;
void setup() {
  Serial.begin(9600);
}
void loop() {
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  delay(1);
  pinMode(2, INPUT);
  value = 0;
  while((digitalRead(2) == HIGH) && (value < 255)) { // <- verific în plus dacă valoarea stocată e sub 255
    delayMicroseconds(40);
    value = value + 1;
  }
  Serial.println(value);
}

note de final:
ledul este sensibil la același tip de lumină pe care o emite. folosind acest principiu, poți foarte ușor să-l transformi într-un senzor de culoare. de asemenea, un led are de obicei o lentilă care dirijează razele de lumină, limitându-i astfel câmpul vizual, la fel ca în cazul emisiei. folosind această informație, poți adapta foarte ușor un led pentru a măsura distanța.

aceast sait folosește cookie-uri pentru a îmbunătăți experiența ta, ca vizitator. în același scop, acest sait utilizează modulul Facebook pentru integrarea cu rețeaua lor socială. poți accesa aici politica mea de confidențialitate.