Universitatea Valahia Târgovişte Facultatea de Inginerie Electrică Specializarea Automatică şi Informatică Industrială
PROIECT DE DIPLOMĂ
DIGITIZAREA DIGITIZAREA AUTOMATĂ A MODELELOR TRIDIMENSIONALE
Student: Banu Cosmin Îndrumător: Conf. Dr. Ing. Dumitrache Cristian Anul: 2006
1
CUPRINS 1. Prezentarea generală a conceptului de scanner 3D 1.1.
Prezentarea temei proiectului
1.2.
Principiul digitizării informaţiei analogice
1.3.
Tipuri de scannere 3D (avantaje şi dezavantaje)
1.4.
Domenii de interes şi utilizări
2.
Algoritmul geometric pentru obţinerea modelului în trei dimensiuni
3.
Descrierea componentelor hardware folosite
4.
5.
6.
3.1.
Folosirea modulului diodă laser pentru linia de scanare
3.2.
Rotirea obiectului cu ajutorul motorului pas cu pas
3.3.
Comandarea laserului şi motorului prin portul paralel
3.4.
Utilizarea camerei video pentru obţinerea datelor de prelucrare
Montajul electric pentru controlarea laserului şi motorului 4.1. .1.
Prot Protec ecţi ţiaa port portul ului ui para parale lell
4.2.
Realizarea controlului motorului pas cu pas
4.3.
Pornirea si oprirea laserului cu ajutorul portului paralel
4.4.
Sursele de alimentare necesare funcţionării circuitelor şi motorului
4.5.
Schema circuitului electric final
Aplicaţiile software folosite pentru dezvoltarea aplicaţiei principale 5.1.
Despre mediul de programare Visual Studio 2005
5.2.
Modele de programare software utilizate (OOP, DP)
5.3.
Lista limbajelor de programare folosite (C#, C++/CLI, XAML)
5.4.
Librăriile Librăriile software utilizate
5.5.
Schema bloc a aplicaţiei finale şi a librăriilor utilizate
Aplicaţia software de control a dispozitivelor şi prelucrare a datelor 6.1.
Librării proprii create pentru a fi utilizate în aplicaţia principală 6.1.1. Clasa ParallelPort (foloseste inpout32.dll) inpout32.dll) realizează trimiterea de date
spre portul paralel 6.1.2. Clasa Laser abstractizeaza controlul laserului (oprirea si pornirea
acestuia) 6.1.3. Clasa Motor configurează şi controlează un motor pas cu pas 2
CUPRINS 1. Prezentarea generală a conceptului de scanner 3D 1.1.
Prezentarea temei proiectului
1.2.
Principiul digitizării informaţiei analogice
1.3.
Tipuri de scannere 3D (avantaje şi dezavantaje)
1.4.
Domenii de interes şi utilizări
2.
Algoritmul geometric pentru obţinerea modelului în trei dimensiuni
3.
Descrierea componentelor hardware folosite
4.
5.
6.
3.1.
Folosirea modulului diodă laser pentru linia de scanare
3.2.
Rotirea obiectului cu ajutorul motorului pas cu pas
3.3.
Comandarea laserului şi motorului prin portul paralel
3.4.
Utilizarea camerei video pentru obţinerea datelor de prelucrare
Montajul electric pentru controlarea laserului şi motorului 4.1. .1.
Prot Protec ecţi ţiaa port portul ului ui para parale lell
4.2.
Realizarea controlului motorului pas cu pas
4.3.
Pornirea si oprirea laserului cu ajutorul portului paralel
4.4.
Sursele de alimentare necesare funcţionării circuitelor şi motorului
4.5.
Schema circuitului electric final
Aplicaţiile software folosite pentru dezvoltarea aplicaţiei principale 5.1.
Despre mediul de programare Visual Studio 2005
5.2.
Modele de programare software utilizate (OOP, DP)
5.3.
Lista limbajelor de programare folosite (C#, C++/CLI, XAML)
5.4.
Librăriile Librăriile software utilizate
5.5.
Schema bloc a aplicaţiei finale şi a librăriilor utilizate
Aplicaţia software de control a dispozitivelor şi prelucrare a datelor 6.1.
Librării proprii create pentru a fi utilizate în aplicaţia principală 6.1.1. Clasa ParallelPort (foloseste inpout32.dll) inpout32.dll) realizează trimiterea de date
spre portul paralel 6.1.2. Clasa Laser abstractizeaza controlul laserului (oprirea si pornirea
acestuia) 6.1.3. Clasa Motor configurează şi controlează un motor pas cu pas 2
6.1.4. Clasa Camera înglobează caracteristicile video şi funcţionalitatea funcţionalitatea unei
camere web 6.1.5. Spaţiul ImageUtils realizează procesarea informaţiei video obţinute de la
camera web 6.1.5.1.
Clasa Filters identifică diferenţele apărute de la o imagine la alta
6.1.5.2.
Clasa Converters converteşte între cele două formate de imagine
6.1.5.3.
Clasa Processors realizează identificarea liniei de scanare şi transpunerea acesteia în spaţiul tridimensional
6.1.6. Clasa Model3D înglobează informaţia obiectului scanat 6.1.7. Clasa Model3DPreview realizează afişarea modelului 6.1.8. Clasa Transforms realizează transpunerea liniei de scanare din imagine
în format bidimensional şi în format tridimensional 6.2.
Aplicaţia principală de configurare şi utilizare a scannerului 6.2.1. Setarea parametrilor pentru scanarea obiectelor 6.2.2. Controlarea scanării obiectului 6.2.3. Vizualizarea Vizualizarea modelului scanat sub diferite forme (nor de puncte, linii de
scanare, mesh, suprafaţă) 6.2.4. Editarea norului de puncte obţinut 6.2.5. Salvarea, încărcarea şi publicarea modelului modelului scanat 7.
Concluzii asupra proiectului final
8.
Sitografie
9. Alte re resurse 10. Anexă cod sursă
3
1. Prezentarea generală a conceptului de scanner 3D
1.1. Prezentarea temei proiectului Proiectul îşi propune realizarea unui scanner de obiecte tridimensionale, folosind un modul diodă laser tip linie, un motor pas cu pas, si o camera web, conectate la un calculator. Scannerul este un scanner fără contact, activ, bazat pe metoda triangulaţiei. Obiectul de scanat este asezat pe o masa rotativă, controlată de un motor pas cu pas. Motorul este controlat la rândul lui prin portul paralel al unui calculator PC. Un modul laser este folosit pentru a „desena” o linie roşie subţire pe obiect. Forma liniei (vazută din alt unghi) este captată cu ajutorul unei camere web, conectata la portul USB al calculatorului. În figura următoare este prezentată o schemă care arată cum sunt poziţionate diferitele componente într-un caz real:
Masa rotativa Camera
Obiect
Laser
Fig. I-1. Elementele constituente ale dispozitivului de scanare
4
Coordonatele camerei, laserului şi obiectului, precum şi orientarea acestora, sunt cunoscute dinainte. La un anumit pas, sunt achiziţionate două imagini de la cameră: una când laserul este stins, şi alta când este aprins. Prin compararea celor două imagini, se poate determina linia laserului. În continuare trebuie stabilită poziţia în spaţiul 3D a fiecărui punct de pe linie. Deoarece se cunoaşte poziţia şi geometria camerei, precum şi pozitia laserului, se poate determina poziţia folosind algoritmul de intersecţie al unei linii cu un plan (linia fiind raza ce porneşte din centrul vizual al camerei şi trece prin respectivul punct roşu de pe linia de scanare; iar planul fiind cel determinat de planul vertical de iluminare al laserului). Aşadar linia roşie este convertită într-o serie de puncte în spaţiul 3D (care este o aproximare digitala a liniei roşii ce iluminează obiectul). Rotind obiectul cu un anumit pas unghiular, putem efectua operaţia din nou, şi obţinem astfel o nouă serie de puncte. Dupa terminarea paşilor, seriile de puncte formează un nor de puncte. Acesta este de fapt norul de puncte ce aproximează suprafaţa obiectului. În continuare, acesta poate fi convertit din serii de puncte în linii, în mesh, sau în suprafaţă poligonală.
1.2. Principiul digitizării informaţiei analogice Proiectul realizează digitizarea modelelor din lumea reală, şi transpunerea lor în spaţiul 3D, pe calculator. Termenul de digitizare este definit astfel: procesul de capturare a caracteristicilor unei entităţi analogice sub forma unei colecţii de digiţi binari, folosind un aparat pentru scanare. Digitizarea este o precondiţie pentru stocarea electronică, cum ar fi stocarea magnetică, sau pe discuri optice. Un exemplu des întâlnit de digitizare este scannerul de documente. Acesta transformă documentul de scanat într-o imagine stocată pe calculator sub format binar. Dezvoltând această idee, putem include aici şi eventuala procesare ulterioară a imaginii obţinute, în scopul recunoaşterii caracterelor (OCR – Optical Character Recognition, Recunoaşterea Optică a Caracterelor).
5
Un scanner 3D este un dispozitiv care analizează un obiect sau un mediu din lumea reală, în scopul colectării de informaţie asupra formei şi chiar culorii acestuia. Informaţiile colectate pot fi folosite apoi pentru construirea unor modele digitale tridimensionale ce pot fi folosite într-o varietate de aplicaţii. Aceste dispozitive sunt folosite extensiv în industrie, în realizarea de exemplu a filmelor şi jocurilor video. Alte întrebuinţări cuprind proiectarea şi realizarea de protipuri, vizualizarea computerizată, documentarea artifactelor culturale, etc.
1.2. Tipuri de scannere 3D (avantaje şi dezavantaje) Există două tipuri de scannere 3D: cu contact, şi fără contact. Scannerele cu contact testează
obiectul prin atingere fizică. Un CMM (maşină de
măsurare a coordonatei) este un exemplu de scanner 3D cu contact. Este în principal folosit în industria manufacturiera şi poate fi foarte precis. Dezavantajul CMM este acela că necesită contactul cu obiectul de scanat. Aşadar, prin simpla scanare a obiectului, acesta se poate modifica sau chiar deteriora. Acest fapt este foarte important dacă este să luăm în considerare obiectele delicate sau foarte valoroase, cum ar fi artifactele istorice. Un alt dezavantaj al CMM-urilor este acela ca sunt relativ încete în comparaţie cu celelalte metode de scanare. Manevrarea fizică a braţului de care este ataşat obiectul poate fi foarte înceată, iar cele mai rapide dispozitive nu pot depăsi câteva sute de herţi. Spre deosebire, un scanner cu laser poate opera de la 10 la 500 kHz. Scannerele fără contact
pot fi împărţite mai departe în două categorii principale,
scannere active şi scannere pasive. Există o varietate de tehnologii în fiecare din aceste categorii. Scannerele active
emit un tip de unde şi detectează reflecţia acesteia pentru a analiza
obiectul sau mediul. Tipuri posibile de unde cuprind razele luminoase, ultrasunetele sau razele X. Scannerele cu timp-de-zbor folosesc lumina laser pentru probarea 6
obiectului. Din moment ce viteza luminii este cunoscută, poate fi folosit timpul-dezbor pentru a determina distanţa (timpul-de-zbor este măsurat ca diferenţa dintre momentul emiterii pulsului laser, şi momentul în care acesta ajunge la detector). Scannerele cu triangulare
sunt tot un tip de scannere active care folosesc lumina laser
pentru a analiza obiectul. Spre deosebire de scannerele cu timp-de-zbor, cele cu triangulare emit o rază laser pe subiect şi folosesc o cameră pentru detectarea poziţiei punctului. În funcţie de distanţa până la obiect, punctul laser apare în poziţii diferite în câmpul de vedere al camerei. Această tehnică se numeşte triangulare deoarece punctul laser, camera şi modulul laser formează un triunghi. Lungimea unei laturi a triunghiului, distanţa dintre cameră şi modulul laser, este cunoscută. Unghiul sub care este poziţionat modulul laser este de asemenea cunoscut, la fel şi unghiul camerei. Cu aceste trei date putem determina precis forma şi dimensiunea triunghiului, şi astfel putem afla poziţia punctului laser. De obicei, în locul unui modul laser de tip punct, este folosit un modul laser de tip linie (care emite o dungă laser). Scannerele pasive
nu emit nici o radiaţie, ci se bazează pe detectarea reflecţiei radiaţiei
ambientale. Majoritatea scannerelor de acest tip detectează lumina vizibilă, deoarece este o radiaţie ambientală deja disponibilă. Alte tipuri de radiaţie, cum ar fi cea în infraroşu, pot fi de asemenea folosite. Metodele pasive pot fi foarte ieftine, deoarece în majoritatea cazurilor nu necesită dispozitive speciale. Sistemele stereoscopice de obicei folosesc două camere video, aşezate una în apropierea celeilalte, şi analizând aceeaşi scenă. Comparând diferenţele subtile dintre imaginile văzute de către fiecare cameră, este posibilă determinarea distanţei până la fiecare punct din imagine. Această metoda se bazează pe vederea stereoscopică a omului. Un alt tip de scannere pasive sunt bazate pe metoda siluetei . Acestea folosesc contururile create de o secvenţă de imagini luate în jurul unui obiect tridimensional care contrastează puternic cu fundalul. Aceste siluete sunt extrudate şi intersectate pentru a forma o „păstaie” vizuală (eng: visual hull) a obiectului. Folosind aceasta tehnică, unele tipuri de concavităţi ale obiectului (cum ar fi interiorul unei vaze) nu sunt detectate. Norii de puncte produşi de scannerele 3D nu sunt de obicei folosiţi în mod direct. Majoritatea aplicaţiilor nu folosesc puncte de nori, ci folosesc modele 3D poligonale în 7
schimb. Procesul de convertire a unui nor de puncte într-un model poligonal 3D poartă denumirea de reconstrucţie . Reconstrucţia constă în detectarea şi conectarea punctelor adiacente cu scopul de a crea o suprafaţă continuă. În acest scop există mai mulţi algoritmi.
1.4. Domenii de interes şi utilizări Posibilitatea de scanare a obiectelor 3D deschide o serie de posibilităţi în diferite domenii, cum ar fi cel manufacturier, arheologic, medical, şi chiar personal. În domeniul manufacturier scannerele pot fi folosite pentru inspectarea suprafeţelor produselor (pentru a ne asigura că obiectele produse se încadrează în standarde), ingineria inversă (eng: reverse engineering), duplicarea obiectelor (producerea de replici). În arheologie, scannerele pot fi folosite pentru a înregistra forma obiectelor, în vederea stocării electronice, sau în scopul prelucrării ulterioare. De multe ori muzeele sunt îngrijorate când sunt puse în situaţia de a expune obiecte fragile, cum ar fi oase de dinozaur, vase din lut, sau ţesături, dar folosind scannerele 3D, acestea pot fi scanate şi replicate, iar originalele sunt păstrate la loc sigur. În domeniul medical, se pot folosi pentru scanarea formei corpului uman, sau a oaselor, pentru proteze dentare. De exemplu putem scana forma unui os rupt, iar prin prelucrarea pe calculator, se poate proiecta proteza. Este posibilă chiar generarea unui duplicat al osului, şi înlocuirea porţiunii afectate cu un os artificial. În domeniul jocurilor pe calculator sau a filmelor, scannerul poate fi folosit pentru digitizarea unor modele deja disponibile.
8
2. Algoritmul geometric pentru obţinerea modelului în trei dimensiuni
Pentru a simplifica modul de explicare, se va considera transpunerea unui singur punct din imaginea obţinută de camera web în spaţiul tridimensional. Datele necesare acestei transformări sunt: poziţia punctului în imagine, unghiul de apertură al camerei (eng: fov angle), aspectul imaginii (eng: aspect ratio), distanţa de la cameră până la centrul de rotire al obiectului, unghiul făcut de laser cu direcţia camerei. În figura următoare sunt prezentaţi parametrii necesari:
dist alfa
wi hi
beta
Fig. II-1. Parametrii geometrici necesari calculării poziţiei punctelor unde: dist – distanţa de la cameră până la centrul de rotire al obiectului alfa – unghiul dintre direcţia laserului şi direcţia camerei beta – unghiul camerei (fov angle) wi – lăţimea imaginii hi – înălţimea imaginii wi/hi – aspectul imaginii (aspect ratio) Fie punctul considerat P(xi, yi) în interiorul imaginii (0 ≤ xi < wi, 0 ≤ yi < hi). Raportând fiecare coordonată la maximul ei, vom obţine valori între 0 şi 1 (x = xi / wi, y = yi / hi). Considerând d distanţa din centrul camerei până la planul de vizualizare al 9
camerei, putem determina în spatiul tridimensional lăţimea şi înălţimea imaginii (d – ct.): w y x
S h
d beta C
Fig. II-2. Parametrii geometrici ai camerei web beta 2
h = 2 ⋅ d ⋅ tg w = h⋅
wi hi
Aşadar, în planul camerei punctul din imagine are coordonatele S(x s, ys, zs), unde: x s
= w( x − 0,5)
y s
= h(0,5 − y )
z s
=0
Punctul de centru al camerei are coordonatele C(0, 0, d). Considerând N normala la planul vertical al laserului, punctul în spaţiu se va obţine astfel: N (cos( alfa ), 0, sin( alfa )) u
=
N ⋅C N ⋅(C −S )
P =C +u ( S −C )
10
3. Descrierea componentelor hardware folosite
3.1. Folosirea modulului diodă laser pentru linia de scanare Laserul (acronim pentru “Light Amplification by Stimulated Emission of Radiation” – “Lumină Amplificată prin Stimularea Emisiei de Radiaţie”) este o sursă optică ce emite fotoni într-un fascicul coerent. Deşi cuvântul LASER provine de la o prescurtare, el a fost inclus în diferite limbi ca un cuvânt separat (un acronim), de aceea el se scrie cu litere mici. În limba engleză, s-a format şi verbul “to lase”, însemnând “producerea de lumina coerentă prin emisie stimulată”. Lumina laser este în mod obişnuit aproape-monocromatică, adică ea consistă dintr-o singură lungime de undă sau culoare, şi este emisă într-un fascicul îngust. Este deci foarte diferită de sursele de lumină obişnuite, cum ar fi becul cu incandescenţă, care emite fotoni incoerenţi în aproape toate direcţiile, pe un spectru larg de lungimi de undă. Laserele variază în dimensiune de la diode laser microscopice (stânga) cu numeroase aplicaţii, până la lasere cu neodim folosite în experimente fizice cu densitate mare de energie (dreapta).
Fig. III-1. Stânga: diodă laser microscopică. Dreapta: laser cu neodim, de putere foarte mare.
11
Componentele laserului
Fig. III-2. Principalele componente ale unui dispozitiv laser. Unde: 1. mediu activ al laserului 2. energie de pompare 3. oglindă 4. oglindă partială 5. fascicul laser Principiul de funcţionare
Se consideră o mulţime de atomi de sisteme cuantice care pentru simplificare, se presupune că au doar două nivele de energie. Toţi atomii fiind identici, au aceeaşi distanţă între cele două nivele de energie (DE). Se presupune de asemenea pentru început că toţi atomii se găsesc în stare fundamentală. Inexistenţa atomilor pe starea superioară face ca la o iradiere cu radiaţia de rezonanţă (perturbare) n=1/h*DE să se petreacă numai tranziţii de jos în sus. Rezultă o absorbţie de energie, fasciculul ce străbate această colectie de atomi va ieşi atenuat. Dacă s-ar reuşi aducerea tuturor (sau cel puţin a majorităţii atomilor) pe nivelul superior, atunci radiaţia incidentă, de frecvenţă de rezonanţă, ar determina tranziţii stimulate, de sus în jos. Rezultă astfel un fascicul de radiaţie mai intens decat cel incident, obţinându-se astfel un fenomen de amplificare a radiaţiei.
12
Problema cheie este deci realizarea situaţiei în care în starea superioară să se găsească un număr mai mare de atomi decât în starea inferioară. Aceasta corespunde unei situaţii de neechilibru şi deci nu poate să persiste decât dacă se consumă energie pentru menţinerea ei. Procesul prin care se realizează această situaţie de neechilibru (denumită şi inversiune de populaţie – inversiune a numărului de atomi, dintr-un ansamblu de atomi identici, care se găsesc într-o stare determinată de energie) se numeşte pompaj. Am putea compara procesul de pompaj cu procesul chimic dintr-o pilă electrică, care menţine o stare de dezechilibru prin continua separare a purtătorilor de sarcină electrică din interiorul ei. Dezvoltând analogia, putem spune că menţinerea unei tensiuni constante la bornele pilei se realizează doar dacă “viteza de separare” a purtătorilor din pilă este mai mare ca viteza de revenire a lor prin circuitul exterior. La fel şi aici, procesul de pompare va trebui sa fie mult mai intens decat cel de dezexcitare. Această condiţie se poate asigura dacă unul dintre nivelele atomului (sau sistemului cuantic) este un nivel metastabil, care în consecinţă determină o dezexcitare mai lentă (viaţa medie mai ridicată ca cea normală).
Fig. III-3. Stânga: experiment folosind un laser (probabil argon). (armata SUA) Dreapta: O demonstraţie cu laser HeNe. (laboratorul Kastler-Brossel, Universitatea 6 Paris) Siguranţa laserului - Clasificare
13
În Statele Unite ale Americii laserele sunt clasificate în funcţie de lungimea de undă şi puterea maximă, în următoarele clase de siguranţă (clasificarea internaţională este puţin diferită): Clasa I – În mod obişnuit sigură; nu există posibilitatea afectării ochiului. Aceasta poate fi datorită puterii mici (în care caz afectarea ochiului este imposibilă chiar şi după ore de expunere), sau datorită unei carcase ce nu poate fi deschisă în timpul operării normale fără ca laserul sa fie oprit automat, cum este cazul unităţilor CD. Clasa II – Reflexul de a clipi al ochiului uman previne afectarea ochiului, atât timp cât persoana nu priveşte fix în fasciculul laser în mod intenţionat. Puterea de ieşire este până la 1mW. Aceasta clasă este pentru lumina vizibilă doar. Clasa IIIa – Laserele din această clasă sunt în principal periculoase atunci când sunt folosite în combinaţie cu instrumente optice care schimbă diametrul fasciculului. Puteri de ieşire de la 1mW la 5mW. Această clasă cuprinde doar lasere cu lumina vizibilă. Majoritatea laserelor “indicator” (eng: laser pointer) sunt incluse în aceasta categorie. Clasa IIIb – Poate dăuna dacă fasciculul pătrunde în ochi direct, sau dacă este reflectat direct în ochi. Aceasta se aplică în general laserelor cu putere de ieşire între 5mW şi 500mW. Reflecţia difuză nu este considerată periculoasă iar laserul nu prezintă pericol de incendiu. Clasa IV – Foarte periculoasă; chiar şi reflectarea difuză indirectă a fasciculului poate duce la afectarea ochiului sau pielii. Se aplică în general pentru lasere cu puteri de ieşire mai mari de 500mW, sau lasere care produc pulsuri intense de lumină. Cu toate că intensitatea fasciculului poate fi doar de câteva ori mai mare decât cea a soarelui strălucitor, în momentul pătrunderii în ochi, fascicul poate fi focalizat într-un punct foarte mic.
14
Puterile laser menţionate mai sus sunt valori tipice; clasificarea este de asemenea dependentă de lungimea de undă, precum şi de modul de operare al laserului (puls sau continuu). De asemenea, chiar şi un laser de putere mare poate fi atribuit unei clase mici de siguranţă dacă este într-o carcasă, astfel încât radiaţia laser să nu o poată părăsi, afectând vreo persoană. Modulul laser folosit
Pentru aplicaţie s-a folosit un “modul de diodă laser generator de linie” (eng: line generator laser diode module) obţinut de la Apinex Inc. Montreal, Canada. Specificaţiile laserului sunt:
Fig. III-4. Laserul LML, procurat de la Apinex Inc.
Clasă: Semiconductor (clasa II sau IIIa) Lungime de undă: 650nm Putere de ieşire: 1mW Circuit: Control Automat al Puterii Sistem Optic: Lentile de plastic tratate anti-reflexie Tensiune de operare: 3V curent continuu Curent de operare: 35mA 15
Temperatură de operare: -10 °C până la +40°C Fascicul: Linie cu deschidere de 90 ° Material carcasă: Alamă Lungime: 40mm Diametru: 11,5mm Lungimea firelor: 120mm
3.2. Rotirea obiectului cu ajutorul motorului pas cu pas Introducere
Motoarele pas cu pas pot fi privite ca motoare electrice fără comutatoare. De obicei, toate înfăşurările din motor fac parte din stator, iar rotorul este fie un magnet permanent, fie, în cazul motoarelor cu reluctanţă variabilă, o piesă dinţată dintr-un material magnetic moale. Toate comutaţiile trebuie manevrate extern de către controlerul motorului, şi de obicei, motoarele şi controlerele sunt proiectate astfel încât rotorul să poată fi ţinut în orice poziţie fixă, şi totodată sa poata fi rotit atât într-un sens, cât şi în celălalt. Majoritatea motoarelor pas cu pas pot fi operate la frecvenţe audio, permiţându-le să se rotească destul de rapid, iar cu un controler potrivit, pot să fie pornite şi oprite cu acurateţe mare la poziţiile dorite. Funcţionarea motorului pas cu pas
16
Fig. III-5. Cei 4 paşi ai secvenţei de rotire a unui motor pas cu pas. Paşi: 1 – electromagnetul de sus (1) este pornit, atrăgând cei mai de sus patru dinţi ai rotorului. 2 – electromagnetul de sus (1) este oprit, iar electromagnetul din dreapta (2) este pornit, atrăgând cei mai apropiaţi 4 dinţi spre dreapta; aceasta rezultă într-o rotaţie cu 3,6°. 3 – electromagnetul din dreapta (2) este oprit, iar electromagnetul de jos (3) este pornit; are loc o altă rotaţie cu 3,6 °. 4 – electromagnetul de jos (3) este oprit, iar electromagnetul din stanga (4) este pornit; se roteşte din nou cu 3,6 °. Când electromagnetul de sus (1) este pornit din nou, dinţii rotorului se vor fi rotit cu o poziţie de un dinte. Din moment ce avem 25 de dinţi pe rotor, vor fi necesari 100 de paşi pentru o rotaţie completă. Tipuri de motoare pas cu pas
Motoarele pas cu pas se găsesc în două varietăţi, cu magnet permanent şi cu reluctanţă variabilă (mai există de asemenea şi motoare hibride, care sunt identice cu cele cu magnet permanent din punctul de vedere al controlerului). În lipsa unei etichete pe motor, le putem distinge prin senzaţia rotirii, când nu sunt alimentate. Motoarele cu magnet permanent tind să “trepideze” când rotim axul cu mâna, în timp ce motoarele 17
cu reluctanţă variabilă au axul ce se roteşte aproape liber (deşi ar putea şi acestea sa “trepideze” puţin, din cauza magnetizării reziduale din rotor). Putem de asemenea distinge între cele două tipuri cu ajutorul unui ohmmetru. Motoarele cu reluctanţă variabilă au de obicei trei înfăşurări, cu un fir comun, în timp ce motoarele cu magneţi permanenţi au de obicei două înfăşurări independente, cu sau fără conexiune la centru. Aceste tipuri de înfăşurări sunt folosite în motoarele cu magneţi permanenţi unipolari. Motoarele pas cu pas au un domeniu larg al rezoluţiei unghiulare. Cele cu rezoluţie mică de obicei se rotesc cu 90 ° la un pas, în timp ce motoarele cu magneţi permanenţi de rezoluţie mare sunt de obicei capabile să se rotească cu 1,8 ° sau chiar 0,72° la un pas. Folosind un controler potrivit, majoritatea motoarelor pas cu pas pot rula cu jumătăţi de pasi (eng: half-stepping, spre deosebire de full-stepping), iar unele controlere pot funcţiona mult mai fin, în modul micro-paşi (eng: micro-stepping). Un fapt valabil pentru ambele tipuri de motoare, atât cele cu magneţi permanenţi, cât şi cele cu reluctanţă variabilă, este acela că dacă doar o înfăşurare este alimentată, rotorul (fără sa fie legat la vreo sarcină) se va poziţiona rapid sub un unghi fix, şi va menţine acea poziţie până când cuplul aplicat asupra axului va depăşi cuplul de sprijin al motorului, moment în care rotorul se va roti, încercând să se menţină fix la fiecare punct de echilibru. Motoare cu reluctanţă variabilă
Fig. III-6. Vedere schematică şi în secţiune a motorului.
18
În figură este reprezentat un motor cu reluctanţă variabilă, cu 3 înfăşurări, 4 fire (3 pentru fiecare înfăşurare, şi unul comun). În practică, firul comun este de obicei conectat la sursă pozitivă, iar înfăşurările sunt alimentate secvenţial. Motorul din figură are pasul de 30 °. Rotorul acestui motor are 4 dinţi iar statorul are 6 poli, fiecare bobină fiind înfăşurată în jurul a doi poli opuşi. Cu înfăşurarea 1 alimentată, dinţii rotorului sunt atraşi de polii acestei înfăşurări. Dacă curentul din înfăşurarea 1 este oprit, şi alimentăm înfăşurarea 2, rotorul se va roti cu 30 ° în sensul invers trigonometric, astfel încât ceilalti doi dinţi ai rotorului se aliniază cu polii bobinei 2. Pentru a roti acest motor continuu, se alimentează cele trei bobine secvenţial. Presupunând logica pozitivă, unde 1 înseamnă alimentarea cu curent a unei bobine, următoarea secvenţă de control va roti motorul în sens invers trigonometric 24 de paşi (2 revoluţii): Înfăşurarea 1:
1001001001001001001001001…
Înfăşurarea 2:
0100100100100100100100100…
Înfăşurarea 3:
0010010010010010010010010…
Motoare unipolare
Fig. III-7. Vedere schematică şi în secţiune a motorului. Motoarele pas cu pas unipolare, atât cele cu magneţi permanenţi cât şi cele hibride, cu 5 sau 6 fire, sunt de regulă conectate ca în figură, cu o conexiune centrală pe fiecare din cele două înfăşurări. În practică, conexiunile centrale ale înfăşurărilor sunt de 19
obicei conectate la sursa pozitivă, iar cele două terminaţii ale fiecărei înfăşurări sunt conectate la masă alternativ pentru a inversa direcţia câmpului generat de acea înfăşurare. Motorul din figură este un motor cu pasul de 30 °, motor cu magnet permanent sau motor hibrid, diferenţa între cele două tipuri de motoare fiind nerelevantă la acest nivel de abstractizare. Înfăşurarea 1 este distribuită intre polul de sus şi cel de jos ale statorului, iar înfăşurarea 2 este distribuită între polul din stânga şi cel din dreapta. Rotorul este un magnet permanent cu 6 poli, 3 poli sud şi 3 poli nord, distribuiţi de-a lungul circumferinţei sale. După cum se vede din figură, curentul care trece de la conexiunea centrală a înfăşurarii 1 până la terminalul ‘a’ face ca polul de sus al statorului să fie un pol nord, iar polul de jos al statorului sa fie un pol sud. Aşadar rotorul este atras în poziţia arătată. Dacă alimentarea înfăşurării 1 este întreruptă şi înfăşurarea 2 este alimentată, rotorul se va roti cu 30°, adica un pas. Pentru a roti rotorul continuu, se alimentează cele două înfăşurări secvenţial. Presupunând logica pozitivă, unde 1 simbolizează alimentarea cu curent a unei înfăşurări a motorului, următoarele două secvenţe de control vor roti rotorul în sens invers trigonometric 24 de paşi, adica 2 revoluţii: Înfăşurarea: 1a
1000100010001000100010001…
Înfăşurarea: 1b
0010001000100010001000100…
Înfăşurarea: 2a
0100010001000100010001000…
Înfăşurarea: 2b
0001000100010001000100010…
Înfăşurarea: 1a
1100110011001100110011001…
Înfăşurarea: 1b
0011001100110011001100110…
Înfăşurarea: 2a
0110011001100110011001100…
Înfăşurarea: 2b
1001100110011001100110011…
20
Se observă că cele două jumătăţi ale fiecărei înfăşurări nu sunt alimentate niciodată simultan. Ambele secvenţe arătate mai sus vor roti un motor cu magnet permanent, cu cate un pas. Secvenţa de sus alimentează doar o înfăşurare la fiecare moment; aşadar, foloseşte mai puţină energie. Secvenţa de jos implică alimentarea ambelor înfăşurări la fiecare moment, şi în general produce un cuplu mai mare de 1,4 ori decât prima secvenţă, consumând totodată de două ori mai multă energie. Poziţiile paşilor produşi de către cele două secvenţe anterioare nu sunt la fel; drept consecinţă, combinând cele două secvenţe se obţine rotirea cu jumătăti de paşi (eng: half-stepping), rotorul oprindu-se alternativ la poziţiile indicate de o secvenţă sau de cealaltă. Secvenţa combinată arată astfel: Înfăşurarea 1a:
11000001110000011100000111…
Înfăşurarea 1b:
00011100000111000001110000…
Înfăşurarea 2a:
01110000011100000111000001…
Înfăşurarea 2b:
00000111000001110000011100…
Motoare bipolare
Fig. III-8. Vedere schematică şi în secţiune a motorului. Motoarele bipolare sunt construite cu exact acelaşi mecanism ca cel din motoarele unipolare, dar cele două înfăşurări sunt conectate simplu, fără conexiuni centrale. Aşadar, motorul în sine este mai simplu, dar circuitul de control al acestuia necesar pentru a inversa polaritatea fiecărei perechi de poli a motorului este mai complex. În figură se arată cum este realizat un astfel de motor, schema de conectare diferă, dar vederea în secţiune este la fel cu cea a motoarelor unipolare. 21
Circuitul de control pentru un asemenea motor necesită o punte H pentru fiecare înfăşurare (în esenţă, o punte H permite ca polaritatea alimentării fiecărei înfăşurări să fie controlată independent). Secvenţele de control pentru rotirea unui astfel de motor sunt arătate în continuare, folosind simbolurile + şi – pentru a indica polaritatea fiecărei terminaţii a fiecărei înfăşurări: Terminaţia 1a: +---+---+---+---
++--++--++--++--
Terminaţia 1b: --+---+---+---+-
--++--++--++--++
Terminaţia 2a: -+---+---+---+--
-++--++--++--++-
Terminaţia 2b: ---+---+---+---+
+--++--++--++--+
Se observă că aceste secvenţe sunt identice cu cele pentru un motor unipolar, la un nivel abstract, deci mai sus de nivelul circuitelor de comutare a puntilor H, sistemele de control ale celor două tipuri de motor poate fi identic. Pentru a putea face distincţia între motorul bipolar cu magneţi permanenţi şi celelalte motoare cu 4 fire, se măsoară rezistenţa între diferitele terminaţii. De menţionat este faptul că unele motoare pas cu pas cu magneţi permanenţi au 4 înfăşurări independente, organizate ca seturi de cate două. În cadrul fiecarui set, dacă cele două înfăşurări sunt înseriate, atunci motorul poate fi folosit ca un motor bipolar de tensiune mare. Dacă sunt montate în paralel, atunci motorul poate fi folosit ca un motor bipolar de tensiune mică. Dacă sunt înseriate, cu conexiune centrală, atunci motorul poate fi folosit ca un motor unipolar de tensiune mică. Motoare bifilare
Aceste tipuri de motoare au geometria statorului şi rotorului identică cu cea a motoarelor bipolare, în schimb înfăşurările fiecărei bobine sunt dublate, cele două fire fiind dispuse în paralel. Drept rezultat, motorul are 8 fire, nu 4.
22
În practică, motoarele cu înfăşurări bifilare sunt de regulă folosite fie ca motoare unipolare, fie ca motoare bipolare. În figură se arată cele două tipuri de conectare ale înfăşurărilor unui astfel de motor.
Fig. III-9. Vedere schematică şi în secţiune a motorului. Pentru a folosi un motor bifilar ca motor unipolar, cele două fire ale fiecarei înfăşurări sunt conectate în serie, iar punctul de conectare este folosit drept conexiune la centru. În figură, înfăşurarea 1 este conectată în acest mod. Pentru a folosi un motor bifilar ca motor bipolar, cele două fire ale fiecarei înfăşurări sunt conectate fie în paralel, fie în serie. Înfăşurarea 2 din figură arată o conexiune paralelă; aceasta permite operarea la tensiune mică şi curent mare. Înfăşurarea 1 din figură arată o conexiune serie; dacă punctul de conexiune la centru este ignorat, aceasta permite operarea la tensiune mare şi curent mic, decât dacă înfăşurările ar fi fost folosite în paralel. Motorul pas cu pas folosit
Pentru aplicaţie s-a folosit un motor pas cu pas cu magnet permanent SPH-39AC-023, produs de Tokyo Electric Co. Ltd., obţinut dintr-o unitate de discheţi magnetici veche. În plus faţă de motorul pas cu pas, o unitate de discheţi de 5,25 inci include şi un motor de curent continuu de 12V cu tahometru şi circuit de control al motorului, două micro-comutatoare, şi o pereche ce include un led şi fotosenzorul corespunzător. Motorul pas cu pas din unitate este un motor cu magnet permanent, unipolar, cu conexiunile centrale unite către un singur fir. Acestea sunt specificaţiile lui: 23
Fig. III-10. Motorul pas cu pas folosit. Tip: cu magnet permanent Polaritate: unipolar Rezoluţia pasului: 3,6 ° Paşi per revoluţie: 100 Tensiune: 12V curent continuu Număr fire: 5 Rezistenţă: 150Ω per înfăşurare (4 x 75Ω ambele înfăşurări)
3.3. Comandarea laserului şi motorului prin portul paralel Introducere
În lumea calculatoarelor, portul paralel este un tip de interfaţă fizică folosită împreună cu un cablu pentru a conecta periferice separate dintr-un sistem de calcul. Prin portul paralel, informaţia binară este transmisă în paralel: fiecare din biţii unei anumite valoari este trimis simultan sub forma unui puls electric pe un fir separat, spre deosebire de portul serial, care necesită ca fiecare din biţi să fie trimis în serie pe acelaşi fir. Numărul de fire şi tipul de conector la un port paralel poate varia.
24
Fig. III-11. Portul paralel al unui laptop Compaq N150. În majoritatea cazurilor, interfaţa USB a înlocuit portul paralel (la momentul scrierii acestui document, marea parte a imprimantelor moderne sunt conectate prin portul USB, şi de multe ori nici nu au nevoie de o conexiune pe portul paralel). Pe multe calculatoare moderne, portul paralel este omis pentru a mai salva din costuri, şi este considerat a fi un port învechit. Aplicaţii
Portul paralel este de obicei folosit de microprocesoare pentru comunicarea cu dispozitivele periferice. Cel mai întâlnit tip de port paralel este portul de imprimantă, port bazat pe conector Centronics ce poate transfera 8 biţi deodată. Discurile dure (eng: HDD disk drives) sunt de asemenea conectate prin porturi paralele speciale, cum sunt cele folosite în tehnologiile SCSI şi ATA. Cu toate acestea, în vorbirea de zi cu zi, portul paralel se referă de obicei la portul de imprimantă al calculatorului PC. Portul paralel al unui calculator compatibil IBM/PC este, de departe, cel mai comun port standard de calculator ce ofera tensiunile logice standard direct la seturile de pini. Este foarte folosit de ingineri (şi amatori) drept un mijloc ieftin de realizare a proiectelor de control prin calculator. Tensiunea logica standard, 5V curent continuu, este inofensivă. Pe de alta parte, circuitul electric al portului paralel este în general destul de fragil; pentru a nu îl deteriora, trebuie sa acordăm atenţia cuvenită. Conectori
25
Portul paralel are de obicei minim 25 de pini, majoritatea fiind folosiţi, ceea ce rezultă în cabluri groase. Aceste cabluri sunt de asemenea limitate în lungime la un maxim de 3 până la 8 metri, în funcţie de portul respectiv şi caracteristicile cablului. Deşi în zilele noastre există mai multe standarde pentru portul paralel, acestea nu sunt întotdeauna respectate (în special în cazul dispozitivelor mai vechi), ceea ce îngreunează procurarea cablului şi aplicatiei software potrivite. Porturile paralele au 4 tipuri de pini: •
Pinii de date (P2–P9), de obicei 8, câteodată 16, şi uneori cu un pin în plus pentru
bitul de paritate. Pot fi atât unidirecţionale (de exemplu de la calculator la imprimantă) cât şi bidirecţionale. Pentru a indica faptul că un bit are valoarea 1, este aplicată o tensiune de 5V pinului respectiv. Lipsa unei tensiuni pe un pin semnifică valoarea 0. Acesta este un mod simplu, dar eficient, de a transmite informaţie digitala pe un cablu analog în timp real. •
Pinii de control, folosiţi pentru a trimite semnale de control cum ar fi STROBE
pentru a indica faptul că datele de pe pinii de date sunt disponibili, şi R/W pentru a specifica dacă porturile bidirecţionale citesc sau scriu date. Pinul STROBE (P1) mentine un nivel al tensiunii între 2,8V şi 5V, dar scade sub 0,5V atunci când calculatorul trimite un octet de date. Această scădere a voltajului anunţă imprimanta de primirea datelor. •
Pinii de stare, folosiţi pentru a trimite semnale ca BUSY pentru a indica faptul că
dispozitivul nu este gata să primească date şi ACK pentru confirmarea primirii reuşite a simbolului. Pinul ACKNOWLEDGE (P10) trimite semnalul de la imprimanta la calculator, şi este folosit pentru a confirma calculatorului primirea datelor. Pinul BUSY (P11) semnalizează faptul că imprimanta este ocupată. •
Pinii de masa, folosiţi pentru a completa circuitele de la ceilalţi pini.
Adresarea portului
Din câte se ştie, sistemele IBM/PC au fost cele care şi-au alocat primele două porturi paralele conform configuraţiei din tabelul de mai jos: 26
Numele portului
Numărul
LPT1 LPT2
întreruperii IRQ 7 IRQ 5
Adresa de start I/O
Adresa de sfârşit
0x378 0x278
I/O 0x37F 0x27F
Interfaţarea cu portul paralel
Portul de imprimantă paralel IBM/PC a avut la început un total de 12 ieşiri digitale şi 5 intrări digitale accesate prin intermediul a 3 porturi consecutive de 8 biţi din spaţiul de adresare I/O al procesorului: •
8 pini de iesire accesaţi prin intermediul portului DATA (D0–D7 ).
•
5 pini de intrare (unul inversat) accesaţi prin intermediul portului STATUS.
•
4 pini de ieşire (trei inversaţi) accesaţi prin intermediul portului CONTROL.
•
Restul de 8 pini sunt legaţi la masă.
Fig. III-12. Pinii portului paralel IBM-PC. De-a lungul timpului, au fost introduse mai multe versiuni imbunătăţite ale originalului: •
Bi-direcţional (PS/2)
•
Portul Paralel Îmbunătăţit (EPP – Enhanced Parallel Port)
•
Portul Extins al Capabilităţilor (ECP – Extended Capability Port) 27
Astăzi, portul original este menţionat ca Portul Paralel Standard (SPP – Standard Parallel Port). Portul paralel folosit în aplicaţie
Portul paralel a fost folosit pentru controlarea prin calculator a motorului pas cu pas, şi a laserului. Pentru controlul laserului (pornire şi oprire) a fost folosit un singur bit. Pentru controlul motorului pas cu pas au fost folosite 4 fire, reprezentând cele 4 terminaţii ale bobinelor motorului. Modul de operare al motorului (cu pas întreg – full stepping – sau cu jumatate de pas – half stepping) este controlat din program. Aşadar, au fost de ajuns 6 fire pentru controlul laserului şi motorului. Tabelul următor arată configuraţia pinilor:
Motor pas cu pas Laser Masă
Pinii conectorului DB25 P2–P5 P6 P18
Pinii de date D0 – D3 D4 –
3.4. Utilizarea camerei video pentru obţinerea datelor de prelucrare Pentru obţinerea fluxului de date video există multe opţiuni. Se poate folosi o cameră video analogică în combinaţie cu o placă de captură video corespunzătoare. O altă variantă este folosirea unei camere digitale controlabilă din calculator. Însă cea mai ieftină modalitate o reprezintă utilizarea unei camere web, conectabilă la calculator prin portul paralel. În cadrul acestui proiect a fost folosită o cameră web Logitech QuickCam Pro 4000:
28
Fig. III-12. Camera web folosită: Logitech QuickCam Pro 4000. Rezoluţie: 160x120, 320x240 Rezoluţie interpolată: 640x480, 1024x768 Interfaţă: USB 2.0
29
4. Montajul electric pentru controlarea laserului şi motorului Partea electrică a proiectului are rolul de a controla prin portul paralel cele două dispozitive: laserul şi motorul pas cu pas. Pentru a controla laserul este de ajuns un bit al portului paralel (am ales bitul 4), iar pentru a controla motorul este nevoie de 4 biţi (am ales biţii 0, 1, 2, 3).
4.1. Protecţia portului paralel Deoarece portul paralel este foarte sensibil referitor la curentul ce poate fi folosit, vom realiza optoizolarea portului folosind optocuploarele 4N35. Intern, un astfel de circuit arată ca în figura următoare:
Fig. IV-1. Optocuplorul 4N35. Un optocuplor (sau optoizolator) este un dispozitiv ce foloseşte o cale optică scurta de transmitere a unui semnal între elementele unui circuit, menţinându-le în acelasi timp izolate electric. Din moment ce se trece dintr-un semnal electric într-un semnal optic şi înapoi într-un semnal electric, contactul electric de-a lungul transformărilor se pierde. O implementare des întâlnită constă dintr-un led şi un senzor de lumină, separate în aşa fel încât lumina să poată parcurge distanţa, dar curentul electric nu. Când un semnal electric este aplicat la intrarea optocuplorului, ledul se aprinde, senzorul de lumina se activează, şi un semnal electric corespunzător este generat la ieşire. Spre deosebire de un transformator, optocuplorul permite lucrul în curent continuu şi de obicei oferă protecţie mai bună în condiţii de supratensiune, astfel încât un circuit să nu îl afecteze pe celălalt. 30
În cazul concret al optocuplorului 4N35, semnalul de intrare trebuie aplicat între pinii 1 şi 2. Pinul 1 va fi legat corespunzător la pinul de date al portului paralel, iar pinul 2 va fi legat la pinul de masă. Când bitul va fi setat prin program pe valoarea 1, între cei doi pini vom avea o tensiune de 5V, ceea ce va face ca ledul sa lumineze. Lumina va ajunge la fototranzistor, care va permite curentului sa treacă prin el, dinspre colector către emitor. Aplicaţia va folosi 5 optocuploare pentru protecţia portului paralel, câte unul pentru fiecare fir de date folosit (patru pentru motorul pas cu pas, şi unul pentru laser).
4.2. Realizarea controlului motorului pas cu pas În figura următoare este reprezentată configuraţia înfăşurărilor din interiorul motorului:
Fig. IV-2. Înfăşurările motorului pas cu pas şi mufa de conectare. Când conexiunea la centru a motorului este conectată la +12V şi un capăt al unei înfăşurări este legat la masă, curentul ce va trece prin înfăşurare se va situa în jurul valorii de 160mA:
U = I ⋅ R ⇒ I =
U R
=
12V 0,75 Ω
31
= 0,16 A =160 mA
Unităţile IBM originale foloseau o pereche de cipuri UDN3612N sau UDN5713. Vom folosi însă circuitul integrat ULN2003 produs de către Allegro Microsystems, care este probabil cel mai răspândit cirtuit de acest tip. Circuitul ULN2003 este format de fapt dintr-o matrice de tranzistoare Darlington. Tranzistorul Darlington este un dispozitiv semiconductor ce combină două tranzistoare bipolare într-un singur dispozitiv astfel încât curentul amplificat de catre primul tranzistor este amplificat mai departe de către al doilea tranzistor. Aceasta îi conferă un factor de amplificare mare, şi foloseşte mai putin spaţiu decât dacă am folosi două tranzistoare normale în aceeaşi configuraţie. Această configuraţie a fost inventată în Laboratoarele Bell de către inginerul Sidney Darlington.
Fig. IV-3. Tranzistor Darlington. Un circuit simplu pentru controlarea motorului prin portul paralel este prezentat în figura următoare (au fost neglijate optocuploarele pentru protecţia portului paralel):
Fig. IV-4. Schema electrică de control al motorului prin portul paralel. Este recomandat să se conecteze o dioda zener între sursa de alimentare şi VDD (pinul 9) de pe circuit, pentru a absorbi forţa electromagnetică inversă generată prin încetarea câmpului magnetic atunci când înfăşurările motorului nu mai sunt alimentate. 32
ULN2003 se alimentează la o tensiune de 5V, spre deosebire de circuitele din aceeaşi familie ULN2002 şi ULN2004 care se alimentează la 14–25V, respectiv 6–15V.
4.3. Pornirea si oprirea laserului cu ajutorul portului paralel Laserul folosit nu prezintă probleme în controlare. Acesta este pornit şi oprit direct din portul paralel (singurul circuit folosit este cel de optoizolare).
4.4. Sursele de alimentare necesare funcţionării circuitelor şi motorului Este nevoie de două surse de tensiune, 12V şi 5V. Cei 12V sunt folosiţi pentru alimentarea înfăşurărilor motorului, iar pentru circuitul integrat ULN2005 sunt folosiţi 5V. Ca sursă de tensiune de 12V este folosit un alimentator de telefon mobil (de la un Alcatel) care se alimentează de la priza (230V curent alternativ, 50Hz). Pentru a obţine 5V, este folosit un circuit integrat regulator de tensiune LM7805. În figura următoare este prezentat un astfel de circuit:
Fig. IV-5. Circuitul integrat LM7805. Pentru realizarea sursei de tensiune este recomandată folosirea unui condensator de 220µ F, deoarece câteodată tensiunea de intrare poate avea un zgomot pronunţat, iar folosirea condensatorului ajută la nivelarea zgomotului.
33
4.5. Schema circuitului electric final
Fig. IV-6. Schema sursei de tensiune de 5V.
Fig. IV-7. Schema de control al laserului.
Fig. IV-8. Schema de control al motorului pas cu pas. Observaţie: Circuitul LM7805 este proiectat să accepte curent de maxim 1A (varianta mai mică a lui, LM78L05 este capabila doar de 100mA), ceea ce este de ajuns pentru alimentarea motorului şi laserului. Motorul consumă pe o fază 160mA, deci va consuma maxim 320mA, în modul de operare cu jumatate de pas – half stepping. Laserul consuma 35mA. În total rezultă un consum maxim de 355mA. La acest nivel 34
al curentului, LM7805 tinde sa se supraîncălzească, de aceea este necesară montarea unui mic radiator pentru disiparea căldurii.
35
5. Aplicaţiile software folosite pentru dezvoltarea aplicaţiei principale
5.1. Despre mediul de programare Visual Studio 2005 Visual Studio 2005 este un mediu integrat de dezvoltare produs de Microsoft. Cu ajutorul acestuia programatorii pot realiza aplicaţii de birou, aplicaţii internet, situri şi servicii web, care rulează pe platforma Windows (calculatoare PC, PDA-uri, telefoane inteligente, etc). El include medii de dezvoltare pentru următoarele limbaje de programare: Visual Basic (pentru limbajul Basic, varianta .NET), Visual C++ (pentru limbajele C, C++, Managed Extensions of C++, şi noul C++/CLI), Visual C# (pentru noul limbaj de programare C#, versiunea 2.0), Visual J#. Microsoft a scos eticheta “.NET” din Visual Studio 2005 (la fel ca oricare alt produs al cărui nume conţinea “.NET”), dar ţinta principală este cadrul de lucru .NET Framework, cea mai recentă versiune fiind 2.0.
5.2. Modele de programare software utilizate (OOP, DP) Din moment ce proiectul foloseşte mai multe limbaje de programare, este necesar să menţionăm modelele de programare folosite de aceste limbaje, sau mai bine spus paradigmele de programare. O paradigmă de programare furnizează (şi determină) modul în care programatorul percepe execuţia programului. De exemplu, în programarea orientată pe obiecte, programatorul se gândeşte la program ca la o colecţie de obiecte ce interacţionează, în timp ce în programarea funcţională un program poate fi perceput ca o secvenţă de evaluări de funcţii fără stare. Multe modele de programare sunt bine cunoscute pentru tehnicile care le interzic, şi mai puţin pentru cele pe care le pun la dispoziţie. De exemplu, programarea funcţională pură interzice folosirea efectelor secundare (apelarea unei funcţii are ca 36
singu singurr efect efect return returnare areaa unei unei valori valori); ); progra programar marea ea struc structur turată ată int interz erzic icee folosi folosirea rea instrucţiunilor de salt (eng: goto). Din aceasta cauză, modelele noi sunt deseori văzute ca doctrinare sau prea rigide de către cei obişnuiţi cu stilurile mai vechi. Relaţia între modelele de programare şi limbajele de programare poate fi complexă din moment ce un limbaj poate suporta multiple modele. De exemplu, C++ este proiectat să suporte elemente din programarea procedurală, din programarea bazată pe obiecte, din programarea orientată pe obiecte şi din programarea generică. Cu toate acestea, proie proiect ctanţ anţii ii şi progra programat matori oriii decid decid cum îşi îşi vor vor dezvo dezvolta lta aplic aplicaţi aţiaa folosi folosind nd acele acele elemente ale modelelor. Cineva poate să scrie un program pur procedural folosind C+ +, altcineva poate să scrie un program orientat pur pe obiecte tot în C++, sau altcineva poate folosi o combinaţie de elemente ale celor două paradigme. OOP – Programarea Orientată Obiect
Ideea care stă la baza programării orientate obiect este aceea ca un program poate fi văzut văzut ca fiind fiind format format dintrdintr-oo mulţim mulţimee de unit unităţi ăţi indiv individu iduale ale,, sau obiect obiecte, e, care care acţionează unul asupra celuilalt, spre deosebire de aspectul tradiţional unde era văzut ca o colecţie de funcţii, sau pur şi simplu de instrucţiuni, executate de calculator. Fiecare obiect este capabil să primească mesaje, să proceseze date, şi să trimită mesaje altor obiecte. Fiecare obiect poate fi văzut ca o mică maşină independentă, sau ca un actor cu un rol distinct sau o responsabilitate distinctă. Programarea orientată obiect este promovată ca prezentând o mai mare flexibilitate şi mentenabilitate în programare, şi este foarte populară în ingineria software de scară largă. Chiar mai mult, cei ce promovează OOP susţin că aceasta este mai uşor de învăţat pentru cei noi în programarea calculatoarelor decât abordările mai vechi, şi că OOP este deseori mai simplu de dezvoltat şi întreţinut, permintând o mai directă analiză, programare şi înţelegere a situaţiilor şi procedurilor complexe, decât celelalte metode de programare. Criticii însă dispută acest lucru, cel puţin pentru anumite domenii (industriale). (industriale).
37
DP – Programarea Declarativă
Există mai multe definiţii pentru programarea declarativă, care ajung să se suprapună. Vom spune despre acest model de programare că se bazează pe următorul principiu: un program este declarativ dacă descrie ce caracteristici are o anumită entitate, decât cum se creează acea entitate sau ce poate face. Privind paradigmele comparativ, comparativ, putem spune pe scurt că programele imperative fac algoritmul explicit lăsând scopul implicit, în timp ce programele declarative fac scopul explicit lăsând algoritmul implicit. Într-un program declarativ se declară o structură de date care este procesată de către un algoritm standard (pentru acel limbaj) producând rezultatul dorit. De exemplu, ăn cazul unei pagini web, se declară cum va arăta pagina în HTML, iar algoritmul browserului traduce această structură în pixeli pe ecran. De asemenea, un limbaj decl declar arat ativ iv,, ca toat toatee limb limbaj ajel ele, e, are are o sint sintax axăă care care desc descri riee cum cum pot pot fi comb combin inat atee cuvintele, şi o semantică ce descrie care este corespondentul propoziţiilor în ieşirea programului.
5.3. Lista limbajor de programare folosite (C#, C++/CLI, XAML) Datorită complexităţii complexităţii aplicaţiei finale, a fost necesară folosirea mai multor limbaje de programare, fiecare cu avantajele şi dezavantajele lui. C# (C Sharp)
C# este un limbaj OOP dezvoltat de către Microsoft ca parte a iniţiativei proprii .NET, care a fost ulterior aprobat ca standard de către ECMA şi ISO. Sintaxa C# este procedurală, orientată obiect, fiind bazată pe cea din C++, şi care include aspecte din mai multe limbaje de programare (ies în evidenţă Delphi, Visual Basic şi Java), punând accentul pe simplificare (mai puţine simboluri decât C++, mai puţine decoraţii decât Java). 38
C# este, din unele perspective, limbajul de programare care reflectă cel mai direct Infr Infras astr truc uctu tura ra Comu Comună nă a Limb Limbaj ajel elor or pe care care se baze bazeaz azăă (eng (eng:: CLI CLI – Comm Common on Lang Langua uagge Infr Infras astr truc uctu ture re). ). A fost fost proi proiec ecta tatt în mod mod spec specia iall pent pentru ru a util utiliz izaa caracteristicile şi avantajele puse la dispoziţie de către CLI. Deşi este un limbaj nou, au trecut mai multe versiuni de la apariţia lui, cea curentă este versiunea 2.0, fiind deja în lucru versiunea 3.0. De la o versiune la alta limbajul a evoluat permanent, pastrând compatibilitatea cu versiunile anterioare (cu excepţia librăriilor librăriilor aferente cadrului de lucru, care au suferit mici modificări). Specificaţia ECMA a C# detaliază un minim set de tipuri şi librării de clase pe care compilatorul se asteaptă să le aibă la dispoziţie, şi care definesc cerinţele de bază. Majoritatea implementărilor vin cu setul de librării extins. C++/CLI
C++/CLI este noua specificaţie a limbajului menit sa înlocuiască varianta C++ cu Extensii de Gestionare (end: Managed Extensions for C++). Fiind o varianta complet revizuită pentru pentru a simplifica simplifica mai vechea vechea sintaxă a Managed C++, C++/CLI pune la dispoziţie dispoziţie mult mai multă claritate în citirea codului. Ca şi Microsoft .NET sau C#, C+ +/CLI este standardizat de către ECMA. Este disponibil deocamdată doar în Visual C+ + 2005. C++/CLI este de fapt un limbaj de sine stătător (cu un nou set de cuvinte cheie, de exemplu), spre deosebire de Managed C++ care era o extensie a C++ (şi folosea cuvinte cheie nestandardizate, cum ar fi __gc sau __value). Din această cauză, există mari schimbari ale sintaxei, legate în special de eliminarea identificatorilor ambigui şi de adăugarea capabilităţilor capabilităţilor specifice .NET. Mai multe conflicte sintactice, cum ar fi multiplele versiuni ale operatorului new din MC++ au fost separate: în C++/CLI, referinţele .NET sunt create cu noul cuvânt cheie 39
gcnew.
De asemenea, C++ a introdus conceptul de generice (similare şabloanelor din
C++, dar destul de diferite). În MC++, existau două tipuri diferite de pointeri: pointeri __nogc erau pointerii C++ normali, în timp ce pointerii __gc lucrau cu referinţele .NET. În C++/CLI singurul tip de pointer este pointerul C++ normal, iar referinţele .NET sunt accesate prin manipulatori (eng: handle), folosind noua sintaxa NumeClasa^ în loc de NumeClasa*. Această nouă construcţie este în special de ajutor când avem de a face cu îmbinări de cod gestionat şi cod nativ; este clar în acest caz care obiecte sunt administrate de către colectorul automat de resturi al .NET (eng: automatic garbage collection), şi care obiecte trebuie distruse manual în cod. XAML (Extensible Application Markup Language)
XAML este limbajul descriptiv al interfeţei cu utilizatorul pentru Fundaţia de Prezentare Windows (eng: WPF – Windows Presentation Foundation), care este unul din pilonii interfeţei de programare pentru .NET Framework 3.0. XAML este un limbaj de programare declarativ bazat pe XML (eXtensible Markup Language), optimizat pentru a descrie interfeţe cu utilizatorul bogate vizual, cum sunt cele create cu Macromedia Flash. Codul XAML este compilat într-un format BAML (Binary xAML), care este mai departe introdus ca resursă în ansamblul aplicaţiei generat de compilator. La execuţie, codul BAML este procesat şi transformat în reprezentarea vizuală a interfeţei. Elementele XAML corespund unor instanţe de obiecte ale CLR (Common Language Runtime). Atributele lor corespund legăturilor WPF, proprietăţilor CLR şi evenimentelor obiectelor respective.
5.4. Librăriile software utilizate
40
Pentru realizarea proiectului a fost necesară folosirea mai multor librării dedicate unor segmente specifice. S-a încercat folosirea unor tehnologii cât mai noi, avansate. La momentul dezvoltării aplicaţiei, librariile pentru interfaţa grafică se află încă în stadiul de beta, ultima versiune fiind cea pentru WinFX Beta 2 (de curând redenumit ca .NET Framework 3.0). .NET Framework (v2.0)
Cadrul de lucru Microsoft .NET Framework este o componenta a sistemului de operare Microsoft Windows. Pune la dispozitie un set mare de cod pentru soluţii la cele mai comune cerinţe ale programelor, şi gestionează execuţia programelor scrise special pentru acesta. El este un produs cheie al Microsoft, şi este menit sa fie folosit de către majoritatea aplicaţiilor noi create pentru platforma Windows. Setul de cod formează librăria de clase a .NET Framework şi acoperă o arie mare a nevoilor de programare din diferite domenii, cum ar fi interfaţa cu utilizatorul, accesul la date, criptografie, algoritmi numerici, şi comunicaţiile prin retea. Funcţiile librăriei de clase sunt folosite de către programatori, care le combină în propriul cod pentru a realiza aplicaţii. Programele scrise pentru .NET Framework sunt executate într-un mediu software care gestionează cerinţele la rulare ale programului. Acest mediu de rulare, care este deasemenea parte a .NET Framework, este cunoscut sub denumirea de CLR (eng: Common Language Runtime). CLR creează aparenţa unei maşini virtuale pentru aplicaţie, astfel încât programatorii să nu mai trebuiască să ia în considerare capabilităţile specifice ale procesorului care va executa aplicaţia. El dispune de asemenea de servicii importante cum ar fi garanţii de securitate, gestionarea memoriei şi tratarea excepţiilor. Conceptul de maşină virtuală a fost împrumutat de la Java cu al său JVM (Java Virtual Machine).
41
Librăria de clase şi CLR-ul formează împreună .NET Framework. Acesta are ca scop simplificarea dezvoltării de aplicaţii pe calculator şi reducerea vulnerabilităţii aplicaţiilor şi calculatoarelor. WPF (Windows Presentation Foundation)
WPF (nume de cod Avalon) este subsistemul grafic al Microsoft Windows. Va fi inclus în Vista, următoarea versiune a Windows. Poate fi folosit şi pe Windows XP SP2 ca parte a .NET Framework 3.0. Dispune de un model consistent pentru dezvoltarea aplicaţiilor, indiferent dacă sunt instalate pe sistem sau sunt rulate dintr-un browser web. Îmbunătăţeşte de asemenea controlul, proiectarea şi dezvoltarea aspectelor vizuale ale programelor Windows. WPF are ca scop unificarea mai multor tipuri de servicii pentru aplicaţii: interfaţa cu utilizatorul, desene 2D şi 3D, documente fixe şi adaptive, grafică vectorială, grafică matriceală, animaţii, legături de date, audio şi video. Din punct de vedere al serviciilor grafice, WPF rutează toate elementele grafice prin Direct3D (interfaţă de programare pentru accesul la accelerarea hardware 3D a plăcilor video). Aceasta permite ca sarcinile grafice sa fie procesate de către procesorul GPU (Graphical Processing Unit) al plăcii video şi nu de către procesorul CPU, care poate executa alte sarcini mai importante în acest timp. Subsistemul grafic este bazat pe grafică vectorială, care îmbunătăţeşte aspectul diferitelor elemente grafice când acestea sunt mărite sau micşorate. Astfel, WPF arată mai bine pe monitoarele de rezoluţie mare, iar cu creşterea numărului de pixeli pe inch, grafica arată mai bine, şi nu mai mică. De asemenea, este posibilă integrarea de conţinut 3D în interfeţele obişnuite. DirectShow
DirectShow (nume de cod Quartz) este o interfaţă de programare a aplicaţiilor produsă de Microsoft pentru ca programatorii să efectueze diferite operaţii cu fişierele media. Fiind bazat pe COM, DirectShow oferă o interfaţă comună pentru diferitele limbaje de programare. 42
Este extensibil, bazat pe filtre, în sensul că programatorul creează un graf de filtre, adaugă câteva filtre la graf (chiar şi filtre proprii), le poate conecta (sau poate lăsa sistemul să le conecteze), şi apoi interpretează (eng: render) un fişier, URL sau o cameră video. În timpul procesului de interpretare, graful de filtre caută în registrul sistemului de operare filtre înregistrate, şi completează graful în funcţie de filtrele găsite. Apoi conectează filtrele, iar din acest moment, la cererea utilizatorului, poate controla afişarea conţinutului media.
Fig. V-1. Graf de filtre pentru redarea unui fişier MP3. Graful este creat în GraphEdit. Fiecare filtru reprezintă o etapă în procesarea datelor (care pot avea ca sursă un fişier, o cameră, sau date provenite de la ieşirea altui filtru). Fiecare filtru are un număr de pini care reprezintă puncte de conexiune către alte filtre. Pinii pot fi de intrare sau de ieşire. În funcţie de filtru, datele sunt consumate de la un pin de intrare, procesate, şi apoi returnate la un pin de ieşire. Majoritatea filtrelor sunt dezvoltate folosind un set de clase C++ din DirectShow, numite Clasele de Baza DirectShow. Acestea gestionează marea parte a creării filtrelor, a înregistrării acestora şi a logicii conectării filtrelor. Direct3D
Direct3D este o tehnologie Microsoft, parte a DirectX. Este disponibilă doar pe sistemele de operare Windows, şi este folosită pentru afişarea de conţinut 3D în aplicaţii unde performanţele sunt importante, cum ar fi jocurile video. Pentru obţinerea acestor performanţe, Direct3D accesează funcţiile de accelerare hardware 3D ale plăcii video. Versiunea folosită în următorul sistem de operare, Windows Vista, este cea cu numărul 10, şi reprezintă un salt important faţă de versiunea precedentă, introducând o suită de concepte noi (de exemplu virtualizarea memoriei). 43
Microsoft pune la dispoziţie şi o versiune pentru limbajele conforme CLI, într-o librărie numită Managed DirectX. Aşadar C# poate fi folosit pentru a crea aplicaţii în Direct3D.
5.5. Schema bloc a aplicaţiei finale şi a librăriilor utilizate
Legenda: Librării proprii implementate în cod Librării disponibile pentru dezvoltare
Fig. V-2. Schema bloc a aplicaţiei finale şi a librăriilor utilizate.
44
6. Aplicaţia software de control a dispozitivelor si prelucrare a datelor Pentru dezvoltarea aplicaţiei principale, din cauza complexităţii ridicate, s-a avut în vedere o abordare cât mai modularizată (organizată pe clase şi librării), care permite împărţirea problemei principale în subprobleme, şi rezolvarea acestora în unităţi mai mici. De asemenea, identificarea eventualelor probleme şi găsirea soluţiilor corespunzătoare devine mai uşoară. Lucrul cu Visual Studio 2005 este bazat pe conceptul de soluţii şi proiecte. Soluţia reprezintă o organizare a tuturor proiectelor pentru o problema dată (în cazul nostru, dezvoltarea programului de scanare 3D). Un proiect este format din totalitatea fişierelor necesare pentru rezolvarea unei subprobleme. Soluţia principală a proiectului conţine mai multe tipuri de proiecte: proiectul aplicaţiei principale, proiectele librăriilor si proiectele aplicaţiilor de test. În acest document vom descrie doar primele două tipuri de proiecte (aplicatiile de test au fost dezvoltate pentru a verifica buna funcţionare a librăriilor).
45
Fig. VI-1. Schema aplicaţiei de scanare şi proiectele ce alcătuiesc soluţia. 6.1. Librării proprii create pentru a fi utilizate în aplicaţia principală
6.1.1. Clasa ParallelPort (foloseste inpout32.dll) realizează trimiterea de date spre portul paralel ParallelPort
Această clasă permite accesarea portului paralel pentru controlarea motorului pas cu pas şi a laserului. Din cauză că versiunile de Windows bazate pe NT (în care este inclus şi Windows XP) impun restricţii de acces la anumite funcţii cum sunt IN şi 46
OUT, a fost necesară folosirea unei librării externe care face ca accesul la portul paralel să se producă uniform pe toate sistemele de operare Windows (98, NT, 2000 şi XP). Librăria folosită se numeşte InpOut32.dll , şi pune la dispozitie două funcţii pentru scrierea şi citirea portului paralel: C++/CLI
void _stdcall Out32(short PortAddress, short data); short _stdcall Inp32(short PortAddress);
Clasa ParallelPort înglobează această funcţionalitate într-o librărie accesibilă pentru limbajele compatibile CLI (cum este C#). Pentru a îmbunătăţi funcţionalitatea oferită, am introdus o variabila de stare ( short mStat e) a portului paralel, ceea ce ne permite să creăm următoarele funcţii: C++/CLI
static void OutputData(Byte data); static void OutputDataBits(Byte data, Byte mask); static void OutputSet(Byte bitmask); static void OutputReset(Byte bitmask); static void OutputToggle(Byte bitmask);
Funcţia OutputData pur şi simplu setează portul paralel pe valoarea transmisă. Funcţia OutputDataBits
face acelaşi lucru, dar foloseşte o mască pentru a lăsa doar anumiţi biţi
să fie setaţi. Următoarele trei funcţii operează pe măşti de biţi, pentru setarea (trecerea pe valoarea 1), resetarea (trecerea pe valoarea 0), şi alternarea/negarea (trecerea din 0 în 1 sau invers) biţilor specificaţi. De asemenea, clasa ParallelPort este protejată pentru accesul de pe multiple fire de execuţie prin folosirea clasei .NET System.Threading.Monitor (monitorizează porţiuni de cod pentru ca accesul să fie individual asupra datelor). C++/CLI
Monitor::Enter(ParallelPort::typeid); try { // seteaza datele } finally
47
{ Monitor::Exit(ParallelPort::typeid); }
Deşi clasa în sine nu creează threaduri, monitorizarea a fost introdusa deoarece alte clase (cum este clasa Motor ) vor folosi mai multe fire de execuţie.
6.1.2. Clasa Laser abstractizeaza controlul laserului (oprirea si pornirea acestuia) Laser
Clasa Laser reprezintă modulul laser, şi este simplă în funcţionalitate, permiţând pornirea şi oprirea laserului. Membrii clasei sunt: C#
private int? mBitLaser; private bool mTurnedOn; public int? BitLaser {…} public bool TurnedOn {…} public void Dispose() {…} private void Dispose(bool disposing) {…}
Primele două linii reprezintă câmpurile private ale clasei, mBitLaser şi mTurnedOn . Ele reprezintă starea laserului la un moment dat. Iniţial laserul este oprit, iar linia de date corespunzătoare lui nu se cunoaşte (este setată pe null ). De observat faptul că este folosit un tip special de variabila ( int?) care de fapt reprezintă o valoare întreaga ce poate fi nulă ( Nullable ). Următoarele două linii reprezintă proprietăţile clasei, accesibile public. Pentru utilizare, întâi trebuie setat care este bitul de laser, prin intermediul proprietăţii BitLaser ,
iar apoi se poate controla pornirea şi oprirea lui modificând valoarea
proprietăţii TurnedOn . După utilizare, este recomandat să se apeleze funcţia Dispose pentru a opri laserul automat. Dacă funcţia nu este apelata manual, ea va fi oricum apelată automat de către 48
colectorul automat de resturi (eng: automatic garbage collector), de obicei la terminarea programului (dar nu neapărat).
6.1.3. Clasa Motor configurează şi controlează un motor pas cu pas Motor
Clasa Motor este destul de complexă în comparaţie cu clasa Laser . Pentru modul de operare s-a optat pentru folosirea rulării cu jumătăţi de pas (half-stepping): Pas 0 1 2 3 4 5 6 7
Faza 4 0 0 0 0 0 1 1 1
Faza 3 0 0 0 1 1 1 0 0
Faza 2 0 1 1 1 0 0 0 0
Faza 1 1 1 0 0 0 0 0 1
Codul secventei 0x01 0x03 0x02 0x06 0x04 0x0C 0x08 0x09
Deci secvenţele din ultima coloană sunt cele care trebuie urmate de sus în jos pentru rotirea într-un sens a rotorului, pentru rotirea în sens invers, secvenţele se iau de jos în sus. C#
// 4-phase half-stepping mode private static readonly byte[] mSequences = { 0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09, 0x00 }; private static readonly double mStepModeReduction = 2.0; private static readonly int mNumSeq = mSequences.Length - 1; private int mSeqIndex = mSequences.Length - 1;
Caracteristicile motorului (rezolutie, sistem reductor, viteza de rulare) sunt specificate prin următorii parametri (accesibili prin proprietatile Resolution , Reduction , MinSpeed şi MaxSpeed , sau prin funcţiile SetParameters şi GetParameters ): C#
// motor specifications private double? mResolution; // angle resolution (degrees) private double? mReduction; // angle reduction (1:reduction)
49
private double? mMinSpeed; private double? mMaxSpeed; public public public public
double? double? double? double?
// minimum rotation speed (rpm) // maximum rotation speed (rpm)
Resolution {…} Reduction {…} MinSpeed {…} MaxSpeed {…}
public void SetParameters( double? resolution, double? reduction, double? minspeed, double? Maxspeed ) {…} public void GetParameters( out double? resolution, out double? reduction, out double? minspeed, out double? Maxspeed ) {…}
Liniile de date prin care se face comanda motorului pas cu pas pe portul paralel sunt specificate prin următorii parametri (accesibili prin proprietăţile BitPhase1 , BitPhase2 , BitPhase3
şi BitPhase4 , sau prin funcţiile SetBits şi GetBits ):
C#
// the data lines bits in clockwise order of the motor coils private int? mBitPhase1; private int? mBitPhase2; private int? mBitPhase3; private int? mBitPhase4; public public public public
int? int? int? int?
BitPhase1 BitPhase2 BitPhase3 BitPhase4
{…} {…} {…} {…}
public void SetBits( int? bitphase1, int? bitphase2, int? bitphase3, int? bitphase4 ) {…} public void GetBits( out int? bitphase1, out int? bitphase2, out int? bitphase3, out int? bitphase4 ) {…}
În momentul lucrului cu motorul, acesta poate fi controlat prin proprietăţile Speed şi Angle ,
având la bază o suită de câmpuri private, necesare stabilirii unghiului curent, 50
unghiului dorit şi vitezei de rotire. Pentru a opera corect în interfeţele grafice utilizator, este folosită execuţia pe un fir separat pentru rotirea motorului. C#
// calculated motor parameters private double? mReferenceAngle; private int? mAngleTicks; private double? mAngleStep; private double? mSpeed; private int? mDeltaTime; // impulses thread Thread mThread; double? mTargetAngle; public double? Speed {…} public double? Angle {…}
Parametrii secundari (cei nedisponibili direct prin intermediul proprietatilor) sunt calculaţi în funcţia ComputeSecondaryParameters . Pentru a afla dacă motorul este gata de operare, în funcţie de setările efectuate, accesăm proprietatea Ready (poate fi doar citită). C#
private void ComputeSecondaryParameters() { if (mSpeed < mMinSpeed) mSpeed = mMinSpeed; if (mSpeed > mMaxSpeed) mSpeed = mMaxSpeed; mAngleStep = mResolution / (mReduction * mStepModeReduction); mDeltaTime = (int?)((mAngleStep / 360.0) * (60000.0 / mSpeed)); } public bool Ready {…}
Firul de execuţie care reglează unghiul rotorului prin trimiterea de impulsuri corespunzătoare secvenţelor de rotire rulează funcţia AngleThread şi este pornit şi oprit cu ajutorul funcţiilor StopMotorThread şi StartMotorThread . Pentru sincronizarea firului de execuţie al motorului cu cel al interfeţei grafice, apelăm funcţia WaitForAngleReached , care utilizează clasa ManualResetEvent din spaţiul de nume System.Threading (este un tip simplificat de semafor). C#
// 'angle reached' signaling ManualResetEvent mMotorStopped = new ManualResetEvent(true); private void AngleThread() {…} private void StopMotorThread() {…}
51
private void StopMotorThread(){…} private void StopMotorThread(){…} public void WaitForAngleReached(){…}
O etapă importantă în obţinerea controlului asupra motorului este determinarea fazelor. Pentru aceasta a fost creată o aplicaţie de test care trece prin toate configuraţiile posibile (pe 4 biti, folosind formula permutărilor, avem 4! = 24 variante), menţinând timp de 3 secunde fiecare din configuraţii. Dintre acestea 24, 8 variante rotesc motorul corect (4 într-un sens, 4 în celălalt sens). Dacă nu s-ar fi folosit o aplicaţie de detectare a ordinii fazelor, tot ar fi fost posibil (destul de uşor) să găsim o configuraţie corectă (8/24 = 33% configuratii corecte). La fel ca în cazul laserului, după terminarea lucrului cu motorul, este recomandat să se apeleze funcţia Dispose pentru a opri firul de execuţie care roteşte motorul, şi a reseta bitii folosiţi ai portului paralel.
6.1.4. Clasa Camera înglobează caracteristicile video şi funcţionalitatea unei camere web Camera
Pentru implementarea acestei clase a fost folosit limbajul C++/CLI, deoarece era necesară interacţiunea cu librăriile DirectShow, şi înglobarea funcţiilor oferite într-o formă accesibilă din C# (la fel ca în cazul clasei ParallelPort). Această clasă înglobează funcţionalitatea unei camere web de care avem nevoie pentru acest proiect. La iniţializarea statică a clasei, sunt detectate toate dispozitivele video de pe calculator care sunt camere web. La fiecare din aceste dispozitive sunt colectate atat descrierea dispozitivului (un şir de caractere unic, identificabil în sistem), cât şi numele acestuia (afişat utilizatorului). Acestea pot fi folosite pentru a permite utilizatorului să selecteze între diferitele camere disponibile în sistem. Colecţia este 52
oferită prin proprietatea Devices (care acceseaza câmpul mDevices ), completată la iniţializare de constructorul static al clasei. C++/CLI
// list of devices found on the system static initonly ReadOnlyCollection^ mDevices; // list of available devices on the system static property ReadOnlyCollection^ Devices {…}
Pentru utilizarea camerei, s-a renunţat la metoda tradiţională de creare a unui obiect prin constructor (acesta a fost declarat protected , deci nu poate fi apelat decât din interiorul clasei), şi s-a abordat stilul fabrică (eng: factory pattern), care ofera o funcţie membru a clasei ce crează obiecte de tipul clasei respective. Aceasta este în cazul nostru funcţia CreateCamera . C++/CLI
protected: // the hidden constructor, used by the factory CreateCamera() Camera(IMoniker *pMoniker, CameraDescription^ description);
function
public: // factory function to create camera objects static Camera^ CreateCamera(int index);
În momentul creării unui obiect de tip cameră, este generat intern graful de filtre DirectShow ce va fi folosit, precum şi creatorul grafului de captură (eng: capture graph builder). Acesta din urmă se va ocupa de conectarea optimă a filtrelor rămase neconectate. Apoi sunt adăugate filtrele preliminare, cum ar fi filtrul sursa al camerei şi filtrul convertor de culoare. Mai departe sunt obţinute interfetele de control al semnalului video, cea de control al camerei şi cea de control al fluxului de date. Aceste interfeţe ne vor da posibilitatea să ajustăm diferitele proprietăţi oferite de cameră. C++/CLI
// the directshow interfaces IGraphBuilder *mpGraph; ICaptureGraphBuilder2 *mpCapture; // the four IBaseFilter IBaseFilter IBaseFilter IBaseFilter
filters that are added to the graph and linked *mpSrcFilter; *mpSmartTee; *mpColor; *mpVmrFilter;
// video signal settings
53
IAMVideoProcAmp *mpVidProcAmp; // camera settings IAMCameraControl *mpCamControl; // resolution control IAMStreamConfig *mpStreamConfig;
Proprietăţile camerei care pot fi setate sunt împărţite în trei categorii: proprietăţile semnalului video ( Brightness , Contrast , Hue, Saturation , Sharpness , Gamma, ColorEnable , WhiteBalance , BacklightCompensation
şi Gain), proprietăţile de control
al camerei ( Pan, Tilt , Roll , Zoom, Exposure , Iris, Focus ) şi proprietăţile fluxului de date ( Resolution ). Rezoluţia poate fi setată în funcţie de colecţia de rezoluţii Resolutions
suportate de către cameră.
C++/CLI
public: property property property property property property property property property property
CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^
Brightness {…} Contrast {…} Hue {…} Saturation {…} Sharpness {…} Gamma {…} ColorEnable {…} WhiteBalance {…} BacklightCompensation {…} Gain {…}
property property property property property property property
CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^ CameraProperty^
Pan {…} Tilt {…} Roll {…} Zoom {…} Exposure {…} Iris {…} Focus {…}
property CameraResolution Resolution {…} property ReadOnlyCollection^ Resolutions {…}
Pentru a porni camera, este necesar întâi să o ataşăm. Previzualizarea poate fi ataşată fie într-o fereastră Windows Forms, fie la o textură 3D în Direct3D (cu ajutorul funcţiilor PreviewWFAttach şi PreviewD3DAttach ). La momentul implementării clasei nu este posibilă ataşarea într-o interfaţă WPF, deoarece nivelul la care este necesară intervenţia nu este disponibil public în API-ul WPF. Pentru a putea totuşi previzualiza camera şi în interfeţele din WPF, în aplicaţia principală s-a folosit tehnologia Crossbow de la Microsoft care permite înglobarea de ferestre şi controale Windows Forms în WPF, şi invers. Ataşarea camerei presupune completarea grafului de filtre cu 54
filtrul VMR9, capabil să afişeze conţinut video în ferestre WIN32 sau în texturi video Direct3D. Pentru afişarea în Direct3D a fost necesară crearea unui filtru special (clasa CameraAP ).
De asemenea utilizatorul trebuie să specifice care sunt dreptunghiurile
sursă (de la semnalul video al camerei) şi destinaţie (spre zona din fereastra/textura de afişare). Odată ataşată previzualizarea, aceasta poate fi controlată cu ajutorul următoarelor funcţii: PreviewPlay, PreviewPause şi PreviewStop. C++/CLI
private: // utility function to destroy the graph void TearDownGraph(); // utility function to build the graph void AssembleGraph(); //utility function to disconnect all pins connected to a base filter void DisconnectAllPins(IBaseFilter *pFilter); protected private: // VMR interfaces IVMRFilterConfig9 *mpConfig; // windowless mode IVMRWindowlessControl9 *mpVMRwc9; // renderless mode IVMRSurfaceAllocatorNotify9 *mpVMRsan9; // Windows Forms attach // the control to which the preview is attached Control^ mWFControl; // the display area and video area preview settings System::Drawing::Rectangle^ mWFDisplayArea; System::Drawing::Rectangle^ mWFVideoArea; // Direct3D Device attach // the device to which the preview is attached Device^ mD3DDevice; // custom allocator/presenter CameraAP* mpCameraAP; // the texture rectangle to which the preview is rendered RectangleF mD3DTextureRect; public: // 'preview' functions void PreviewWFAttach(Control^ wfcontrol); void PreviewD3DAttach(Device^ d3ddevice); void PreviewDetach(); void PreviewStop(); void PreviewPause(); void PreviewPlay();
Pentru a face o poză cu camera apelăm funcţia TakePicture . Deoarece modul în care operează VMR9 este fie fără fereastră proprie (eng: windowless), adică în Windows 55
Forms, fie fără randare (eng: renderless), adică în Direct3D, funcţia TakePicture va întoarce
rezultatul
uneia
din
funcţiile
TakePictureWindowless
sau
TakePictureRenderless . C++/CLI
private: // utility function to take picture while in windowless mode Bitmap^ TakePictureWindowless(); // utility function to take picture while in renderless mode Bitmap^ TakePictureRenderless(); public: // take a picture Bitmap^ TakePicture();
Şi în cazul clasei Camera, după încetarea lucrului cu dispozitivul, este recomandată apelarea funcţiei Dispose pentru a elibera resursele.
6.1.5. Spaţiul ImageUtils realizează procesarea informaţiei video obţinute de la camera web ImageUtils.Filters, ImageUtils.Converters, ImageUtils.Processors
Spaţiul de nume ImageUtils conţine câteva clase care se ocupă cu procesarea informaţiilor provenite de la camera web. Funcţiile din aceste clase sunt statice, deci nu este necesară crearea unei instanţe a claselor respective pentru accesarea funcţionalităţii acestora.
6.1.5.1. Clasa Filters identifică diferenţele apărute de la o imagine la alta Filters
56
Clasa Filters conţine două funcţii de determinare a modificărilor apărute în fluxul video, de la o imagine la alta. Sunt implementaţi doi algoritmi, DiffFilter şi MotionDiffFilter. În aplicaţia principală este folosită doar funcţia DiffFilter. C++/CLI
public ref class Filters { public: static Bitmap^ DiffFilter(Bitmap^ before, Bitmap^ after); static Bitmap^ MotionDiffFilter(Bitmap^ before, Bitmap^ after); };
Cele două funcţii primesc ca parametri două obiecte de tip Bitmap şi întorc un nou obiect de acelaşi tip. Algoritmul funcţiei DiffFilter face diferenţa pentru fiecare componentă a culorii (roşu, verde, albastru) între imaginea after şi cea before (D = A – B). Algoritmul funcţiei MotionDiffFilter este puţin diferit. Acesta calculează întâi o valoare medie a celor trei componente de culoare din ambele imagini, şi apoi face diferenţa. Dacă valoarea obţinută este pozitivă, este reglată intensitatea componentei roşu din imaginea finală. Dacă este negativă, este reglată intensitatea componentei albastru. Componenta verde este setată la valoare maximă.
57
Fig. VI-2. Imaginea iniţială ( before), imaginea finală ( after ), imaginea obţinută cu DiffFilter , şi imaginea obţinută cu MotionDiffFilter .
6.1.5.2. Clasa Converters converteşte între cele două formate de imagine Converters
Clasa pune la dispoziţie o singură funcţie, care realizează conversia între cele două tipuri de obiecte imagine folosite: clasa Bitmap (din spaţiul de nume System.Drawing) şi clasa BitmapSource (din spaţiul de nume System.Windows.Media.Imaging, folosită în WPF). Conversia este necesară pentru a putea afişa imagina obţinută de la webcam în interfaţa aplicaţiei creată în WPF. C++/CLI
public ref class Converters { public: static BitmapSource^ ConvertBitmap(Bitmap^ bitmap); };
6.1.5.3. Clasa Processors realizează identificarea liniei de scanare şi transpunerea acesteia în spaţiul tridimensional Processors
58
Operaţia de transpunere a liniei laserului din imagine într-o curbă în spaţiul 3D este efectuată în două etape. Clasa Processors pune la dispoziţie funcţia pentru efectuarea primei etape: transformarea liniei din imagine într-o linie de scanare în spaţiul 2D al imaginii (parametrizarea liniei de scanare). Aceasta este efectuată de către funcţia GetScanLine2DFromImage .
Cea de-a doua funcţie este folosită pentru obţinerea unei
reprezentări pe ecran a parametrizării liniei. C++/CLI
public ref class Processors { public: static ScanLine2D^ GetScanLine2DFromImage(Bitmap^ redline, int threshold); static Bitmap^ DrawScanLine2DtoImage(int width, int height, ScanLine2D^ scanline, Color bg, Color fg); };
Mai jos este arătată imaginea liniei laser pe un obiect (stânga) şi reprezentarea parametrizării ei (dreapta).
Fig. VI-3. Imaginea liniei laser identificată, şi parametrizarea acesteia. 6.1.6. Clasa Model3D înglobează informaţia obiectului scanat Model3D
Această clasă realizează înglobarea tuturor informaţiilor scanate, şi nu numai. Informaţia scanată este structurată într-o listă de linii de scanare ( List ). Iniţial, modelul nu conţine nici o linie. Pe măsura ce este realizată scanarea obiectului, 59
sunt adăugate noi linii de scanare cu ajutorul funcţiei AddScanline() . La finalul scanării trebuie setată proprietatea FullScan (dacă modelul a fost scanat prin rotire completă), şi apoi apelată funcţia SetScanComplete() , care marchează sfârşitul scanării. C#
List mScanLines; public void AddScanLine(ScanLine3D scanline) {…} SetScanComplete(){…} public bool FullScan { get {…} set {…} }
Liniile de scanare sunt prelucrate pentru a putea fi afişate pe ecran în cele patru variante: puncte, linii, mesh şi suprafaţă. Funcţiile care se ocupă de acest lucru sunt Update3DContent*() .
funcţii
ca:
Pentru implementarea micului editor din aplicaţie, sunt folosite
SelectPoints() ,
SelectAllPoints() ,
InvertSelectedPoints() ,
SmoothSelectedPoints() , DeleteSelectedPoints(), etc. C#
private private private private private public public public public
void void void void void
void void void void
Update3DContentPoints() {…} Update3DContentLines() {…} Update3DContentWireframe() {…} Update3DContentSurface() {…} Update3DContentAll() {…} SelectPoints(Rectangle selrect) {…} DeSelectPoints(Rectangle selrect) {…} SmoothSelectedPoints(){…} DeleteSelectedPoints(){…}
De afişarea pe ecran se ocupă funcţiile Render*() . Pentru ca acestea să funcţioneze, modelului îi trebuie ataşată o instanţă de tip Model3DPreview , care este de fapt un control ce foloseşte Direct3D şi primeşte instrucţiuni de afişare din partea modelului. Acest control este setat cu ajutorul funcţiei SetPreview() . C#
Model3DPreview mPreview; public void SetPreview(Model3DPreview preview) {…} public void RenderPoints() {…} public void RenderLines() {…} public void RenderWireframe() {…} public void RenderSurface() {…}
De asemenea pentru realizarea stocării şi încărcării modelelor, sunt folosite o serie de funcţii ce lucrează în formatul XML. Pentru salvarea şi încarcarea fişierelor de tip 60
.model
sunt folosite funcţiile GetModelXml() şi LoadFromXml() . Pentru salvarea
modelului în format X3D sunt folosite funcţiile Get*X3D() . Fişierul de descriere al modelului (pentru crearea galeriei de modele de pe serverul web) este creat cu ajutorul funcţiei GetPublishXml() . C#
public public public public public public public public
XmlDocument GetModelXml(){…} void SaveAsXml(string filename) {…} static Model3D LoadFromXml(string filename) {…} XmlDocument GetPublishXml(){…} XmlDocument GetPointsX3D(){…} XmlDocument GetLinesX3D(){…} XmlDocument GetWireframeX3D(){…} XmlDocument GetSurfaceX3D(){…}
6.1.7. Clasa Model3DPreview realizează afişarea modelului Pentru afişarea modelului este folosită componenta Direct3D a DirectX, varianta gestionata (Managed DirectX). Pentru a putea fi folosit, trebuie iniţial setat modelul ce va fi afişat, prin intermediul proprietăţii Model . Modul de vizualizare şi control al camerei foloseşte coordonate sferice (două unghiuri, pe orizontala şi verticală, şi distanţa până la obiect). C#
// the D3D device private Device mDevice; // camera parameters - spherical private float mAlpha; private float mBeta; private float mDist; // model private Model3D mModel; public Model3D Model { get {…} set {…} }
6.1.8. Clasa Transforms realizează transpunerea liniei de scanare din imagine în format bidimensional şi în format tridimensional În cadrul algoritmului de obţinere a formei liniei de iluminare în spaţiul 3D s-a discutat doar despre prima etapă, cea de parametrizare a imaginii ce conţine linia roşie a 61
laserului. Cea de-a doua etapă este de fapt cea mai importantă etapă din algoritmul de triangulare, şi anume aceea de transformare a liniei de scanare din spaţiul 2D al camerei, în cel 3D. Funcţia care face acest lucru este ScanLine2DToScanLine3D() . C#
public static ScanLine3D ScanLine2DToScanLine3D( // scanline ScanLine2D scanline, // camera geometry double fovangle, double aspectratio, // scene geometry double distance, double laserangle, double motorangle) {…}
6.2. Aplicaţia principală de configurare şi utilizare a scannerului Dispozitivul de scanare în sine (format din motorul pas cu pas, modulul diodă laser, circuitul de control şi camera web) este coordonat de aplicaţia de scanare Object Scanner .
Aceasta se foloseşte de toate librăriile discutate până acum pentru
determinarea formei obiectului, vizualizarea acestuia în diferite moduri şi stocarea modelului. Iniţial, la pornire, aplicaţia va prezenta următoarea interfaţă:
62
Fig. VI-4. Interfaţa principala a aplicaţiei de scanare. Pentru a începe lucrul cu aplicaţia de scanare, iniţial trebuie setaţi parametrii de rulare. Aceştia pot fi configuraţi accesând cele 5 butoane din partea superioară a interfeţei: Laser Setup, Motor Setup , Camera Setup, Camera Geometry , Position Geometry şi Scan Job Parameters .
După configurarea parametrilor, poate fi pornită scanarea obiectului. Butoanele de control a scanării obiectului sunt: Start , Pause , Stop şi Reset . Atât în timpul scanării, cât şi după terminarea acesteia, modelul poate fi vizualizat în partea din stânga a interfeţei, la Object Preview. Pe toată durata scanării, în Camera Preview este afişat fluxul video venit de la camera web, iar în dreapta interfeţei, la Processing Preview pot fi analizate imaginile procesate de cameră, şi rezultatele parametrizării liniei de scanare curente. După terminarea scanării, modelul poate fi inserat în lista de obiecte scanate. Această listă este controlată cu ajutorul butoanelor Grab, Preview, Rename , Remove . De 63
asemenea, modelele din această listă pot fi salvate şi încărcate de pe spaţiul local de stocare (discul dur) folosind butoanele Save şi Load . Pentru publicarea modelului pe un server FTP, se foloseşte butonul Publish .
6.2.1. Setarea parametrilor pentru scanarea obiectelor Laser Setup
La apăsarea butonului Laser Setup, va apărea fereastra de setare şi testare a laserului. Pentru oprirea şi pornirea laserului este necesară o singura linie de date a portului paralel. Cele două butoane servesc pentru testarea funcţionării corecte a laserului.
Fig. VI-5. Configurarea parametrilor laserului. Motor Setup
Fereastra de configurare şi testare a motorului pas cu pas este mai complexă. Se pot seta cei 4 biţi ai portului paralel ce vor fi folosiţi, precum şi ordinea acestora (ordinea fazelor poate fi descoperită destul de repede prin încercări, existând 24 de configuraţii posibile, dintre care 8 rotesc motorul corect într-un sens sau în celalalt). Următorul parametru ce trebuie setat este rezoluţia motorului, în acest caz 3,6 °. Parametrul gear reduction
este util în cazul folosirii angrenajelor de reducere a rezoluţiei, în lipsa
acestora parametrul trebuind setat la 1,0. Următorii parametri sunt legaţi de viteza de rotire a motorului şi nu prezintă importanţă deosebită. Pentru testarea configuraţiei sunt puse la dispoziţie 5 butoane (rotire continuu stânga, rotire pas stânga, stop, rotire pas dreapta, rotire continuu dreapta). 64
Fig. VI-6. Configurarea parametrilor motorului. Camera Setup
Setarea camerei consta în alegerea camerei ce va fi folosită (în caz că sunt disponibile mai multe în sistem), a rezoluţiei acesteia, şi configurarea parametrilor de imagine: Brightness , Contrast , Gamma , Gain, Exposure , Sharpness .
Pentru a vedea calitatea
imaginii şi în cazul folosirii laserului, acesta poate fi pornit şi oprit prin apăsarea butonului Toggle Laser .
Fig. VI-7. Configurarea parametrilor camerei.
65
Camera Geometry
Geometria camerei se referă la câmpul vizual al acesteia. Trebuie configurat unghiul fov (eng: field of view), şi aspectul imaginii (adica raportul dintre lăţimea imaginii, şi înălţimea acesteia).
Fig. VI-8. Configurarea geometriei camerei. Position Geometry
Parametrii geometriei de poziţie descriu aşezarea celor 3 componente ale scannerului în scenă (camera, motor, laser).
Fig. VI-9. Configurarea parametrilor geometrici de poziţie. Scan Job Parameters
Aceşti parametri se referă la modul de scanare al obiectului. Start Angle şi Stop Angle determină procentul din suprafaţa obiectului, care va fi scanat. În cazul de faţă rotirea se efectuează cu 360 °, deci scanarea va fi completă. Parametrul Ticks Per Step indică numărul de paşi cu care se va roti motorul pentru fiecare linie scanată. 66
Fig. VI-10. Configurarea parametrilor de scanare.
6.2.2. Controlarea scanării obiectului Scanarea obiectului poate fi controlată prin intermediul butoanelor Start, Pause, Stop şi Reset.
Fig. VI-11. Butoanele de control a procesului de scanare. Butonul Start porneşte procesul de scanare a obiectului. Dacă se doreşte întreruperea pe moment a scanării, se foloseşte butonul Pause . Pentru a relua scanarea din locul de unde a fost întreruptă, se apasă din nou butonul Pause , sau butonul Start . Scanarea va continua până la epuizarea tuturor paşilor de scanare. Dacă se doreşte finalizarea prematură a scanării, poate fi folosit butonul Stop. Acesta întrerupe complet scanarea, fără a pierde informaţiile deja culese. Butonul Reset este folosit pentru a reiniţializa spaţiul de lucru, şi a porni o nouă scanare (nu poate fi începută o nouă scanare fără apăsarea butonului Reset ).
6.2.3. Vizualizarea modelului scanat sub diferite forme (nor de puncte, linii de scanare, mesh, suprafaţă) Modelul scanat poate fi vizualizat în fereastra Object Preview atât după terminarea scanării, cât şi în timpul acesteia. În timpul scanării, ultima linie de scanare adăugată 67
va fi reprezentată cu roşu. Modelul poate fi analizat prin rotire, folosind butonul stânga al mausului.
Fig. VI-12. Diferite moduri de vizualizare a obiectului scanat.
6.2.4. Editarea norului de puncte obţinut Norul de puncte obţinut poate fi editat rapid pentru înlăturarea unor artifacturi, cum ar fi platforma de rotire ce apare în cazul unei scanări normale. Selectarea punctelor se face cu ajutorul butonului stânga al mausului, ţinând apăsată tasta Control. Pentru deselectare, se foloseşte combinaţia de taste Control-Alt. Pentru ştergerea punctelor se apasă tasta Delete. Există şi o opţiune de netezire a liniilor de scanare, ce poate fi efectuată asupra punctelor selectate folosind combinaţia de taste Control-M. Toate aceste funcţii de editare se regăsesc şi în cadrul meniului contextual al controlului, ce poate fi accesat apăsând butonul dreapta al mausului. 68
Fig. VI-13. Editarea modelului scanat.
6.2.5. Mijloace de stocare a modelului scanat Modelul scanat poate fi stocat şi încărcat atât local, pe discul dur, folosind formatul propriu .model , cât şi publicat pe un server FTP, putându-se crea astfel o galerie cu modelele scanate. Fereastra de publicare pe serverul FTP este numită Ftp Publish. Este necesară specificarea adresei serverului de FTP, a numelui sub care va fi stocat modelul, precum şi a numelui de utilizator şi a parolei de acces.
Fig. VI-5. Publicarea modelului pe internet. În urma operaţiei de publicare, pe serverul FTP vor fi stocate cinci fişiere: descrierea modelului în format XML, şi cele patru moduri de vizualizare (nor de puncte, linii de
69
scanare, mesh şi suprafaţă) în format X3D. Folosind un plugin pentru deschiderea fişierelor X3D, modelul poate fi vizualizat direct în browser.
Fig. VI-5. Vizualizarea modelului in cadrul galeriei online.
70
7. Concluzii Proiectul de faţă reuşeşte, fără a folosi echipamente sofisticate, să realizeze un dispozitiv de scanare a obiectelor 3D în vederea digitizării formei acestora. Trebuie avute în vedere mai multe aspecte care influenţează calitatea informaţiei obţinute: rezoluţia mică a camerei web, rezoluţia mică a motorului pas cu pas, considerente legate de metoda de scanare folosită, algoritmul implementat de generare a suprafeţelor. Rezoluţia camerei web
Camera folosită dispune de o rezoluţie mică, 320x240, suficientă pentru scopuri demonstrative, dar innacceptabilă în cazul unui produs comercial. Folosind o cameră digitală de rezoluţie mare (de la 1MP în sus), se va obţine o formă mult mai detaliată a fiecărei linii de scanare (de exemplu, la rezoluţia de 1024x768 se poate obţine un maxim de 1024 de puncte pentru fiecare linie de scanare). Rezoluţia motorului pas cu pas
Motorul folosit în acest proiect are o rezoluţie de 3,6 °, ceea ce înseamna 100 de linii de scanare la o scanare completă a obiectului. Folosind un motor de rezoluţie mai mare (1,8°; 0,9°; 0,72°; etc.), sau un sistem reductor (angrenaje formate din roţi dinţate dispuse special), se poate mări numărul de linii de scanare obţinute. De exemplu, dacă s-ar fi folosit un sistem reductor cu un factor de reducere de 3,0, motorul s-ar fi rotit cu 1,2° la fiecare pas, deci s-ar obţine 300 linii de scanare. Există spre comercializare astfel de motoare, dotate direct din fabrică cu sistem reductor, cum ar fi motorul LSG35 produs de Hurst Manufacturing Inc. Sistemul reductor poate atinge un factor de 300 (LSG35012E98P), ceea ce înseamnă o rezoluţie de 0,1 ° la fiecare pas (3600 linii de scanare la o scanare completă). Considerente legate de metoda de scanare folosită
71
Din cauza faptului că laserul ce luminează obiectul este aşezat sub un anumit unghi faţă de direcţia de vizualizare a camerei, obiectul nu este scanat complet. În anumite poziţii, camera nu poate vedea complet linia trasată de laser (aceasta se întâmplă în special când se ajunge la colţurile obiectului). Pentru a reduce din acest handicap, ar trebui folosit un unghi al laserului cât mai mic. Aceasta rezultă într-o scanare aproape completa a obiectului (desigur în cazul unui unghi de 0 °, scanarea este completă). Unghiurile mici însa afectează calitatea curbei detectate, de aceea la unghiuri mici se poate observa un zgomot pronunţat al liniilor de scanare (în cazul unghiului de 0 °, forma liniei nu poate fi detectată). Un unghi mai mare asigură o bună detectare a formei liniei laserului. De aceea trebuie realizat un compromis între aria de scanare a obiectului şi calitatea scanării obţinute. Un unghi potrivit este cel de 30 °. Algoritmul implementat de generare a suprafeţelor
În cazul aplicaţiei de faţă, pentru demonstraţie, suprafaţa este generată pornind de la liniile de scanare, folosind un algoritm propriu. Însa într-un caz real aplicaţia de scanare nu va fi cea care va genera din norul de puncte suprafaţa corespunzătoare. Pentru acest scop exista aplicaţii de grafică speciale, care folosesc algoritmi avansaţi de generare a suprafeţei (procesul poartă denumirea de “reconstruire a suprafeţei”, iar algoritmii sunt de obicei bazaţi pe diagrame Voronoi şi triangulaţii Delaunay).
72
Bibliografie: [1] Scanner cu laser 3D (data consultării: Noiembrie 2005) http://www.muellerr.ch/engineering/laserscanner/ [2] Despre scannerele 3D (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/3D_scanner [3] Module de lasere generatoare de linii LML (data consultării: Februarie 2006) http://www.apinex.com/ret2/lmlan.html [4] Laser (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/Laser [5] Motorul pas cu pas (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/Stepper_motor [6] Despre motoarele pas cu pas (data consultării: Martie 2006) http://www.cs.uiowa.edu/~jones/step/index.html [7] Portul paralel (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/Parallel_port [8] Cum funcţioneaza portul paralel (data consultării: Mai 2006) http://computer.howstuffworks.com/parallel-port.htm [9] Ieşirea pe portul paralel (data consultării: Martie 2006) http://www.epanorama.net/circuits/parallel_output.html [10] Controlul motorului pas cu pas prin portul paralel (data consultării: Martie 2006) http://www.doc.ic.ac.uk/~ih/doc/stepper/control2/connect.html
73
[11] Un exemplu de control al motorului pas cu pas (data consultării: Martie 2006) http://www.electronics-lab.com/projects/pc/006/index.html [12] Programarea Orientata Obiect (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/Object_oriented_programming [13] Programarea Declarativa (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/Declarative_programming [14] C# (C Sharp) (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/C_sharp [15] C++/CLI (C++ / Common Language Infrastructure) (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/C%2B%2B/CLI [16] XAML (eXtensible Application Markup Language) (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/XAML [17] .NET Framework (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/.net_framework [18] Windows Presentation Foundation (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/Windows_Presentation_Foundation [19] DirectShow (data consultării: Aprilie 2006) http://en.wikipedia.org/wiki/DirectShow [20] Formatul X3D (data consultării: Iunie 2006) http://www.web3d.org/x3d/specifications/
74
[21] Geometry compendium (data consultării: Iunie 2006) http://astronomy.swin.edu.au/~pbourke/geometry/
75