Simulator HardSoft pentru motoare electrice [307668]
UNIVERSITATEA “TITU MAIORESCU” DIN BUCUREȘTI
FACULTATEA DE INFORMATICĂ
LUCRARE DE LICENȚĂ
Simulator Hard/Soft pentru motoare electrice
comandate cu automate Siemens
COORDONATOR ȘTIINȚIFIC:
Lect.univ.dr.ing. Dan-Laurențiu GRECU
ABSOLVENT: [anonimizat]
2015
UNIVERSITATEA TITU MAIORESCU
FACULTATEA DE INFORMATICĂ
DEPARTAMENTUL DE INFORMATICĂ
REFERAT
DE APRECIERE A LUCRĂRII DE LICENȚĂ
TITLU: Simulator Hard/Soft pentru motoare electrice comandate cu automate Siemens
ABSOLVENT: [anonimizat]: Lect.univ.dr.ing. Dan-[anonimizat]:
[anonimizat]/disertație întrunește/ nu întrunește condițiile pentru a fi susținută în fața comisiei pentru examenul de licență/disertație din sesiunea
__________________________ și o apreciez cu nota ___________________
CONDUCĂTOR ȘTIINȚIFIC,
______________________________
1. Introducere
Odată cu dezvoltarea tehnologiei automatele programabile sunt tot mai des utilizate în activitățile industriale și domestice datorită numeroaselor avantaje pe care le prezintă.
Controlul bazat pe feedback a [anonimizat]. Inițial, [anonimizat], o [anonimizat].
[anonimizat], utilizează feedbackul efectuând o măsurare a senzorilor, comparând-o cu valoarea de referință dorită și reglând o ieșire de control pe baza acestei diferențe.
[anonimizat], [anonimizat], utilizarea unui radiator sau ventilator pentru a aduce temperatura cât mai aproape de valoarea de referință dorită.
[anonimizat] a determina în ce măsură trebuie reglate ieșirile de control pentru a obține cel mai bun răspuns.
[anonimizat]? Regulatorul PID de bază compară o singură intrare cu o valoare de referință și calculează o valoare de ieșire unică pentru a [anonimizat]. [anonimizat].
Obiectivul principal al acestei lucrări este de a realiza un program ce permite simularea unui motor electric având la dispoziție automatul programabil SIMATIC S7 1200 și programul software TIA Portal V11, [anonimizat]. Tema aleasă reprezintă un exercițiu foarte bun pentru înțelegerea:
[anonimizat] S7 1200
modului de utilizare al unui sistem PID (Proporțional-Integral-Derivative)
[anonimizat], cum ar fi PIC18F4550 în limbajul C++, utilizând softul MPLAB-X
modului de programare în Java a unei tablete cu sistemul de operare Android folosind Eclipse și librăria AndEngine cu extensia Physics Box2D
[anonimizat] (Proporțional-Integral-Derivative), implementat în automatul programabil Siemens SIMATIC S7 1200 folosind un simulator software implementat pe o tabletă cu sistemul de operare Android.
In capitolele care urmează vor fi prezentate noțiunile teoretice care stau la baza proiectului, o prezentare generală a sistemului, o descriere Hardware în care se va detalia cum sunt conectate la nivel fizic echipamentele, o descriere Software în care este detaliat fiecare componentă soft care a fost realizată pentru funcționarea ansamblului.
Cel mai important capitol fiind „Modul de funcționare” în care se detaliază funcționarea întregului sistem și mai exact cum se conectează hardware-ul în funcție de modul care dorim să îl operăm pe Tabletă sau Microcontroler.
Scopul lucrării este de a implementa un PID în cadrul PLC-ului Siemens, prin care acesta va controla o simulare software implementată pe Tabletă, aceasta simulare fiind de fapt un motor electric care va pune în mișcare o roată mai mare, având ca sursă de comandă PLC-ul. Pe Tabletă vom putea acționa o frână asupra roții pentru a vedea cum reacționează PID-ul implementat pe PLC în timp real.
Vom aborda subiectul din punct de vedere hardware, capitolul cuprinzând descrierea fiecărui echipament folosit în cadrul lucrării de licență, scheme electronice pentru subansamblele Microcontrolerului, descrierea generală și cum se configurează folosind software-ul TIA Portal PLC-ul SIMATIC S7-1200 de la Siemens.
Vom mai aborda subiectul din punctul de vedea al implementării software, capitolul „Descriere software” conține informații despre codul sursă și funcționarea în tandem ale celor trei aplicații implementate pe PLC, Microcontroler cât și pe Tabletă. Această parte fiind cea mai complexă și necesită cunoștințe de JAVA, C++ și LAD.
În ultimul rând vom descrie cele două moduri de funcționare punând accent pe modul de simulare al motorului electric, acesta fiind și scopul acestei lucrări de licență. Vom descrie de asemenea două studii de caz care au fost reproduse în cadrul laboratorului folosind întreg ansamblul care cuprinde Panoul didactic, plăcile de conectare și Tableta.
2. Noțiuni teoretice
2.1. Noțiuni generale. Locul și rolul regulatorului automat în sistemul de reglare automată
Regulatorul automat (RA) are rolul de a prelucra operațional semnalul de eroare ε și de a da la ieșire un semnal de comandă xc pentru elementul de execuție. Este plasat pe calea directă, între elementul de comparație și elementul de execuție.
Informațiile curente asupra procesului automatizat se obțin cu ajutorul traductorului de reacție TR și sunt prelucrate de regulatorul automat RA în conformitate cu o anumită lege care definește algoritmul de reglare automată (leg ea de reglare).
Implementarea unei anumite legi de reglare se poate realiza printr-o varietate destul de largă a construcției regulatorului, ca regulator electronic, pneumatic, hidraulic sau mixt.
Orice regulator va conține următoarele elemente componente (figura 2.):
amplificatorul (A)
elementul de reacție secundară (ERS)
elementul de comparare secundară (ECS)
Amplificatorul (A) este elementul de bază. El amplifică mărimea ε1 cu un factor KR, deci realizează
o relație de tipul:
,
unde KR reprezintă factorul de amplificare al regulatorului.
Elementul de reacție secundară ERS primește la intrare mărimea de comandă xc (de la ieșirea amplificatorului) și elaborează la ieșire un semnal xrs denumit mărime de reacție secundară. ERS este de obicei un element care determină o dependență proporțională între xrs și xc.
Elementul de comparare secundară (ECS) efectuează continuu compararea valorilor abaterii ε și a lui xrs după relația:
Din punct de vedere constructiv regulatorul automat include de obicei și elementul de comparație EC al sistemului de reglare automată. În cazul sistemelor de reglare unificate, electronice sau pneumatice, el poate include și dispozitivul de prescriere a referinței.
Regulatorul poate avea o structură mai complicată. De exemplu, la unele regulatoare există mai multe etaje de amplificare, la altele există mai multe reacții secundare necesare obținerii unor legi de reglare mai complexe.
2.2. Răspunsul regulatoarelor automate la semnalul treaptă unitară
În figura 2. este dată reprezentarea convențională a unui semnal treaptă unitară, considerând că valoarea anterioară m1 este nulă, iar trecerea la m2 = 1 se face la momentul inițial t = 0.
a. Regulatoare cu acțiune proporțională (de tip P)
Aceste regulatoare stabilesc între mărimea de ieșire xc(t) și mărimea de intrare ε(t) o relație de dependență proporțională descrisă de :
unde KR este factorul de amplificare al regulatorului.
Datorită inerției elementelor componente ale regulatorului mărimea de comandă nu poate urmări instantaneu variația erorii și din această cauză variația reală a mărimii xc(t) este trasată punctat.
Adesea în loc de KR se utilizează factorul numit bandă de proporționalitate BP definit ca fiind acel procent din domeniul mărimii de intrare în regulator ε(t) pentru care regulatorul de tip P determină o valoare xc(t) egală cu 100% din domeniul posibil pentru mărimea de ieșire.
Când domeniul de variație al erorii ε este egal cu domeniul de variație al mărimii de comanda xc (cazul regulatoarelor unificate), banda de proporționalitate se determină:
Dacă domeniul de variație al mărimii ε(t) diferă de cel al lui xc(t) , atunci banda de proporționalitate BP se determină cu relația:
Factorul de proporționalitate KR, respectiv banda de proporționalitate BP, reprezintă unicul parametru al regulatoarelor de tip P. Prin construcția regulatorului P acest parametru se prevede a fi ajustabil în limite largi pentru a satisface o varietate mare de legi de reglare. Astfel, dacă mărimile de la intrarea și ieșirea regulatorului au același domeniu de variație, KR poate fi variat între 50 și 0,5, ceea ce corespunde unei benzi de proporționalitate cuprinse între 2% și 200%
b. Regulatoare cu acțiune integrală (de tip I)
Aceste regulatoare stabilesc între mărimea de ieșire xc(t) și mărimea de intrare ε(t) o relație de dependență descrisă de :
.
Mărimea xc(t) depinde de integrala în timp a erorii ε(t). Constanta Ti se numește constantă de integrare și are dimensiunea timp.
În figura 4. este reprezentat răspunsul la intrare treaptă al unui regulator de tip I.
Derivând în funcție de timp relația , se obține:
Rezultă că la regulatorul de tip I viteza de variație a mărimii de comandă este proporțională cu eroarea, factorul de proporționalitate fiind inversul timpului de integrare.
Răspunsul regulatorului de tip I la intrare treaptă este un semnal rampă cu coeficientul unghiular:
.
Parametrul ajustabil al regulatorului I este timpul de integrare care poate fi variat în diverse limite, de la ordinul fracțiunilor de secundă până la zeci de minute, în funcție de tipul regulatorului, pentru procese rapide sau procese lente.
Regulatoarele de tip I sunt rar utilizate datorită întârzierilor pe care le introduc. Se aplică atunci când se dorește eroare staționară nulă și nu există alte elemente ale sistemului de reglare automată care să permită aceasta.
c. Regulatoare cu acțiune proporțional integrală (de tip PI)
Aceste regulatoare reprezintă o combinație între un regulator de tip P și unul de tip I și stabilesc între mărimea de ieșire xc(t) și mărimea de intrare ε(t) o relație de dependență descrisă de :
.
Factorii KR și care caracterizează cele două componente ale răspunsului regulatorului pot fi modificați independent unul de celălalt.
Relația mai poate fi scrisă și:
,
unde este constanta de timp de integrare a regulatorului. Ea prezintă avantajul că factorul de proporționalitate KR intervine atât în componenta proporțională cât și în componenta integrală, astfel că modificarea lui KR permite modificarea ambelor componente. Aceasta corespunde condițiilor constructive reale ale celor mai multe regulatoare de tip PI.
În figura 5. este reprezentat răspunsul la intrare treaptă al unui regulator de tip PI.
Datorită posibilității de combinare a celor două acțiuni, proporțională și integrală, prin modificarea simultană a celor două constante, regulatoarele PI permit obținerea de caracteristici superioare în realizarea legilor de reglare.
d. Regulatoare cu acțiune proporțional derivativă (de tip PD)
Aceste regulatoare, similar celor de tip PI, reprezintă o combinație între un regulator de tip P și unul de tip D și stabilesc între mărimea de ieșire xc(t) și mărimea de intrare ε(t) o relație de dependență descrisă de :
,
unde factorul Td se numește constantă derivativă și are dimensiunea timp.
Similar ca la regulatoarele PI, relația poate fi scrisă și:
,
unde factorul se numește constantă de timp derivativă a regulatorului și are dimensiunea timp.
În figura 6. este reprezentat răspunsul la intrare treaptă al unui regulator de tip PD.
Din aceleași considerente ca la regulatoarele PI, se preferă ca dependența determinată de regulatoarele PD să fie exprimată prin a doua relație, deoarece din punct de vedere constructiv, prin modificarea factorului KR este permisă și modificarea constantei de timp derivative. Unele regulatoare sunt prevăzute cu dispozitive care permit variația simultană a lui KR și a lui TD, astfel ca produsul KR·TD să rămână constant.
Analizând răspunsul la intrare treaptă al unui regulator PD se observă ca acțiunea componentei derivative se manifestă numai la momentul inițial, când are loc saltul mărimii de la intrare. Prezența componentei derivative care apare la momentul inițial și este de scurtă durată, are ca efect o accelerare a regimului tranzitoriu și deci o reducere a acestuia. Comparativ cu regulatoarele de tip P sau cele de tip I, aceste regulatoare permit posibilități mai largi de realizare a legilor de reglare.
e. Regulatoare cu acțiune proporțional integrală derivativă (de tip PID)
Aceste regulatoare sunt cele mai complexe regulatoare cu acțiune continuă, care asigură performanțe de reglare superioare, atât în regim staționar cât și în regim tranzitoriu. Ele înglobează efectele proporțional P, integral I și derivativ D expuse mai sus, conform legii de reglare:
+.
Dacă se ține seama de realizarea constructivă a regulatorului, relația poate fi scrisă:
.
Răspunsul la intrare treaptă al unui regulator de tip PID este reprezentat în figura 7. în care se observă prezența celor trei componente P, I și D:
Regulatoarele PID au trei parametri ajustabili KR, TI, TD, ceea ce asigură posibilități mult mai largi în asigurarea legilor de reglare decât la oricare din regulatoarele descrise anterior și explică performanțele superioare ale sistemelor de reglare automată prevăzute cu aceste regulatoare. Evident că regulatoarele PID au construcții mai complexe și necesită o acordare atentă a valorilor celor trei parametri.
Pentru a evidenția influența tipului de regulator asupra comportării SRA, în figura 8. au fost trasate răspunsurile în timp ale mărimii de ieșire dintr-un SRA, xe(t), pentru o variație treaptă a mărimii de intrare xi, în condițiile în care sunt utilizate regulatoarele P, PI, PD și PID.
Comparându-se curbele de răspuns, se pot face următoarele aprecieri:
• regulatorul de tip P reduce apreciabil suprareglajul, conduce la un timp tranzitoriu scurt, dar introduce o eroare staționară εst mare;
• prin introducerea componentei I, regulatorul de tip PI anulează eroarea staționară la intrare treaptă, însă duce la un suprareglaj mai mare decât la regulatorul P și la o valoare mare a timpului de răspuns;
• prin introducerea componentei D regulatorul de tip PD îmbunătățește comportarea dinamică (suprareglajul σ și durata regimului tranzitoriu sunt mici), însă menține o eroare staționară mare;
• regulatorul de tip PID, combinând efectele P, I și D, oferă performanțe superioare atât în regim stationar, cât și în regim tranzitoriu.
2.3. Clasificarea regulatoarelor automate
1. În funcție de sursa de energie exterioară folosită, acestea se clasifică în:
regulatoare automate directe – funcționează fără o sursă de energie exterioară, transmiterea semnalului realizându-se pe seama energiei interne preluată direct din proces prin intermediul traductorului de reacție;
regulatoare automate indirecte – necesită o sursă de energie exterioară pentru acționarea elementului de execuție. Sunt cele mai utilizate regulatoare care permit obținerea unor caracteristici funcționale mai complexe și performanțe superioare regulatoarelor directe.
2. După viteza de răspuns există:
regulatoare automate pentru procese rapide folosite pentru reglarea automată a parametrilor proceselor cu răspuns rapid, caracterizate de constante de timp mici (mai mici de 10 s), ca de exemplu procesele de tip acționări electrice.
regulatoare automate pentru procese lente folosite atunci când constantele de timp ale instalației sunt mari (depășesc 10 sec), situație frecvent întâlnită în cazul proceselor având ca parametri: temperaturi, presiuni, debite, nivele etc.
3. După tipul acțiunii regulatoarele pot fi:
regulatoare automate cu acțiune continuă – sunt cele în care mărimile ε(t) și xc(t) variază continuu în timp;
regulatoare automate cu acțiune discontinuă sau discretă, la care cel puțin una din mărimile ε(t) și xc(t) variază discontinuu în timp, de exemplu ca trenuri de impulsuri (modulate în amplitudine sau durată). În această categorie intră regulatoarele bi sau tripoziționale, la care ε(t) variază continuu dar xc(t) poate lua un număr limitat de valori în raport cu eroarea.
Regulatoarele cu acțiune continuă la rândul lor pot fi:
regulatoare automate liniare dacă dependența dintre cele două mărimi este liniară;
regulatoare automate neliniare dacă dependența dintre cele două mărimi este neliniară.
4. După caracteristicile constructive există:
regulatoare automate unificate, utilizate pentru reglarea a diferiți parametri (temperatură, presiune, etc.). Regulatoarele unificate funcționează cu un anumit tip de semnal ce variază în limite fixate, atât la intrare cât și la ieșire. Semnalele cu care funcționează aceste regulatoare sunt semnale unificate și au aceleași valori ca la sistemele de măsurare și control unificate, respectiv 2…10mA sau 4…20mA pentru regulatoarele electronice unificate și 0,2…1bar pentru cele pneumatice.
regulatoare automate specializate, utilizate numai pentru un anumit parametru tehnologic, au structura constructivă și semnalele de lucru special concepute pentru parametrul considerat.
5. După agentul purtător de semnal există:
regulatoare automate electronice, la care atât mărimea de intrare cât și mărimea de ieșire sunt de natură electrică (intensitatea curentului electric sau tensiunea electrică) și care au în componența lor blocuri electronice;
regulatoare automate hidraulice (ulei sub presiune);
regulatoare automate pneumatice (aer comprimat);
regulatoare automate mixte (electropneumatice sau electrohidraulice).
6. După numărul mărimilor de ieșire ale instalației tehnologice:
regulatoare automate monovariabile (pentru o singură mărime reglată)
regulatoare automate multivariabile (pentru mai multe mărimi reglate).
Multe procese industriale sunt caracterizate prin faptul că au mai multe intrări ce generează ca efecte mai multe ieșiri, cu puternice interacțiuni între variabile. Pentru exemplificarea unui asemenea model considerăm procesul cu două intrări și două ieșiri reprezentat în figura 1. Intrările în proces sunt cele două debite de fluide Q1 și Q2 care alimentează un rezervor și care se află la temperaturi diferite θ1, respectiv θ2. Ieșirile măsurabile ale procesului sunt nivelul lichidului din rezervor (H) și temperatura (θ). Procesele multivariabile, în situații speciale, bine definite, pot fi controlate cu regulatoare monovariabile, prin descompunerea SRA multivariabil în mai multe bucle de reglare cu o intrare și o ieșire.
3. Prezentarea generală a sistemului
În imaginea de mai jos este prezentat modelul general al unui PID implementat pe un automat programabil. Din punct de vedere funcțional, dacă perturbația poate fi măsurată, atunci ieșirea compensatorului poate fi reglată imediat pentru a răspunde. De pildă, dacă un ventilator introduce aer rece într-o cameră termică, ieșirea radiatorului poate fi crescută imediat, mai degrabă decât să aștepte prima dată, ca temperatura din imediata apropiere a senzorului să scadă. Reglarea în caz de perturbații este o variație pe sistemul de control PID, care ajută sistemele cu răspuns lent la perturbații.
PID cu reglare cu acțiune directă
În imaginea de mai sus, un senzor de perturbații este măsurat, multiplicat de anumite valori de amplificare definite de utilizator, iar apoi, adăugat la valoarea de ieșire PID. Dacă perturbațiile cresc, canalul de ieșire al compensatorului va crește imediat pentru a menține controlul sistemului. Această abordare nu este întotdeauna necesară, deoarece creșterea parametrului de gain proporțional pe un compensator PID tradițional va îmbunătăți în același timp, anularea perturbațiilor și nu necesită ca acestea să fie măsurate.
Noi în actualul proiect de licență am realizat un PID pentru controlul unui motor electric, acesta punând în mișcare o roată mai mare prin forța de frecare, în funcție de viteza de rotire a roții mari vom trimite un feedback înapoi pentru ca PID-ul să compenseze și să anuleze perturbațiile.
Sistemul este format din trei parți de bază care se pot vedea în schema bloc de mai sus:
Sistemul de automatizare care cuprinde următoarele secțiuni
PLC-ul Siemens SIMATIC S7-1200, acesta fiind CPU-ul
SM1223 și SM1234 care reprezintă modulele pentru comunicarea analogică și digitală, aceste având porturi de comunicare și sunt conectate la CPU
Software-ul cu care va fi programat PLC-ul
Microcontrolerul care are mai multe componente
Placa principală care conține microcontrolerul PIC18F4550
Software-ul care va controla cipul
Placa de testare
Placa de conectare cu PLC-ul SIMATIC S7-1200
Simularea software instalată pe Tabletă
Secțiunea de testare pentru a putea vedea cum se comportă intrările și ieșirile digitale respectiv analogice
Secțiunea pentru simularea roții unui motor electric care va învârtii o altă roată folosind ca transfer de mișcare forța de frecare
Sistemul de automatizare care are ca componentă principală PLC-ul Siemens SIMATIC S7-1200 în care va fi implementat un PID, modul de funcționare și calculele sunt prezentate în capitolul „Noțiuni teoretice”, acest PID fiind implementat în aplicația TIA Portal v11. PLC-ul va controla pe baza unui Setpoint și a Feedback-ului primit tensiunea de ieșire de la conectorul Output.
In momentul în care sistemul de automatizare este pornit și dorim simularea motorului să funcționeze, în PID-ul programat va fi setat un Setpoint la un anumit nivel, sa zicem 40%. Acest lucru se realizează prin rotirea potențiometrului de pe poziția AI1 a Panoului Didactic.
In acest moment în blocul DIV implementat în PLC se va face conversia din numărul de la 0 la 29600 la un număr de la 0 la 100, acest număr fiind trimis la blocul PID, care va mări tensiunea de pe pinul Output.
Microcontrolerul are rolul de primire/trimitere a informației intre Tableta si PLC, convertind această informație din electricitate în date pentru a putea fi interpretate de către software-ul de pe PLC și/sau de pe tabletă.
Tensiunea trimisă de către sistemul de automatizare va fi citită de Microcontroler și transformată într-un număr care va fi trimis prin conexiunea USB la software-ul instalat pe Tabletă.
Microcontrolerul nu ia decizii, el doar transformă tensiuni în date și invers, acestea fiind transmise nemodificat la Tableta/PLC.
Simularea software interpretează datele primite și folosindu-se de librăria Box2D va aplica un impuls asupra roții motorului. Această roată începând să se învârtă, cu ajutorul forței de frecare va pune în mișcare o a doua roată. Transferul de mișcare se bazează pe foarte multe forțe, greutatea roții fiind configurată în cadrul aplicației, de asemenea și cât de aderent sau alunecoase sunt corpurile.
Pe baza vitezei de rotire a celei de-a doua roți se va calcula un număr care reprezintă tensiunea măsurată la bornele unui generator de curent.
Acest număr va fi trimis prin conexiunea USB la Microcontroler, care îl va interpreta și va trimite tensiunea respectiva la PLC. Aceasta tensiune este între 0v si +5v.
In funcție de acesta tensiune primită, PLC-ul va ajusta tensiunea de pe canal pentru a menține tensiunea de intrare la setarea inițiala de 40%. Tensiunea furnizată de către PLC este intre 0 si +10v.
Fluxul este bidirecțional între elemente și este transformat din date în semnale electrice și invers de către Microcontroler și PLC.
Pe sensul dinspre PLC înspre tabletă prima data se va acționa potențiometrul de pe panoul didactic, acesta furnizând pe unul din conectorii analogici o tensiune, această tensiune este citita de către PLC și acel semnal electric va fi transformat într-o cifra în memoria PLC-ului. Aceasta cifră va fi transformată de către softul PLC-ului din numărul respectiv de la 0 la 29600 într-o mărime de la 0 la 100, acest lucru se face prin dividerea numărului primit la 296, unde numărul rezultat de la 0 la 100 reprezintă un procent.
In acest moment avem un „Setpoint” pentru blocul PID implementat în cadrul PLC-ului, acest bloc software va ridica tensiunea pe conectorul de Output la care este conectat Microcontrolerul.
Microcontrolerul va citi aceasta tensiune și o va transforma într-un număr, acest număr stocându-l în memorie și îl va trimite la Tabletă prin conexiunea USB stabilită.
Software-ul de pe Tabletă va interpreta acest număr și va acționa în consecință, rotind roata motorului care la rândul ei va pune în mișcare roata cea mare print-un transfer de mișcare utilizând forța de frecare.
In momentul în care roata cea mare se pune în mișcare, softul de pe tabletă va știi acest lucru și va scrie într-o zona de memorie valoarea vitezei cu care roata se învârte, această valoare va fi trimisă către Microcontroler.
După ce Microcontrolerul primește datele anterior calculate el va ridica tensiunea pe pinul respectiv pană la valoarea reprezentată de viteza de rotire a roții. Această tensiune este citită de către PLC și cu ajutorul ei, PLC-ul va calcula cu cât trebuie să compenseze tensiunea de pe Output pentru ca viteza motorului să rămână constantă.
In acest proiect de licență avem control asupra frânei exercitate pe roata mare și de asemenea a vitezei de rotire la care se dorește să se țină viteza constantă, controlată prin potențiometrul AI1. Putem din aplicația software să selectăm mai multe valori de referință care ne pot face să înțelegem cum funcționează întreg sistemul în diversele cazuri pe care le vrem urmărite.
Ca exemplu putem pune o putere mai mică a motorului și o frâna mai mare, sau o putere mai mare a motorului și o frâna mai mică. În ambele situații putem măsura timpul de reacție pentru a aduce la viteză constantă roata secundară, învârtită de către motor.
Acum începem prezentarea componentelor sistemului care va cuprinde o descriere din punct de vedere hardware, o descriere din punct de vedere software și de asemenea punerea în funcțiune, testarea modului de funcționare al simulatorului.
4. Descriere hardware
4.1. Sistemul de automatizare SIMATIC S7-1200
4.1.1. Generalități
PLC este abrevierea pentru Programmable Logic Controller cunoscut ca și automat programabil. Acesta este un dispozitiv care comandă un proces (de exemplu: o presă de tipărit ziare, o instalație pentru umplerea cu ciment a sacilor, o presă pentru injecția formelor de plastic, etc.). Acest lucru se realizează în conformitate cu instrucțiunile unui program care se află în memoria dispozitivului.
Automatizarea este o ramură a tehnicii, al cărei scop este ca mașinile și instalațiile să lucreze automat, deci independente de o continuă și/sau directă intervenție a forței de muncă umane. Cu cât acest țel este realizat mai optimal, cu atât este mai ridicat gradul de automatizare. În instalațiile automatizate operatorul uman preia sarcini de supraveghere, de aprovizionare cu material, de transport a produselor finite, de întreținere și alte activități similare. Noile realizări ale electrotehnicii (microprocesoare) accelerează hotărâtor procesele de automatizare. Pe lângă protejarea forței de muncă umane de activități grele și monotone, automatizarea ridică calitatea produselor precum și productivitatea proceselor cu o reducere corespunzătoare a costurilor pentru resursele umane folosite.
Sistemul de automatizare SIMATIC S7-1200 este un sistem mini-controler modular din gama de performanțe scăzute. Familia S7-1200 cuprinde o gamă largă de module pentru adaptarea optimă la necesitățile de automatizare. Controlerul S7 constă dintr-o unitate centrală de procesare CPU care este echipat cu intrări și ieșiri pentru semnale digitale și analogice.
In cazul în care intrările și ieșirile integrate în CPU nu sunt suficiente pentru aplicația dorită, pot fi instalate modulele de intrare și de ieșire (module IO) suplimentare. Dacă este necesar, se adaugă procesoare de comunicare pentru RS232 sau RS485. O interfață TCP / IP integrată este obligatorie pentru toate unitățile centrale de procesare CPU.
Automatul programabil (PLC) monitorizează și controlează un utilaj sau un proces cu ajutorul programului S7, care asigură interogarea modulelor IO prin intermediul adreselor de intrare (%I) și comanda procesului prin intermediul adreselor de ieșire (%Q).
Sistemul de automatizare SIMATIC S7-1200 este programat cu software-ul TIA Portal V11.
4.1.2. Configurarea și utilizarea automatului programabil SIMATIC S7-1200
Gama de module: Sistemul de automatizare SIMATIC S7-1200 este un sistem modular care a fost echipat cu următoarele module:
Modulul unității centrale CPU de diverse capacități, intrări / ieșiri integrate și interfață PROFINET (fig.1)
Fig.1 CPU1214C
Sursă de alimentare PM cu intrare de 120/230V curent alternativ, 50Hz/60Hz, 1.2A/0.7A și ieșire de 24V/2.5A curent continuu (fig.2)
Fig.2 PM 1207
Module de extensie de semnal SM (fig.3)pentru intrări și ieșiri analogice și digitale suplimentare (împreună cu unitățile centrale CPU 1212C pot fi utilizate un număr de maxim 2 module de extensie de semnal SM, în timp ce cu CPU 1214C se pot utiliza maximum 8 module de extensie de semnal SM)
Fig.3 SM 1223 DC/DC
Ansamblul complet din laborator (fig.4) pe care a fost realizat acest proiect de licență este furnizat în cadrul laboratorului de Informatică Aplicată în Industrie. Aceasta este configurația fizică în care a fost implementat proiectul de licență.
Fig.4 Configurația hardware din laborator
Panoul didactic conține mai multe porturi de intrare și de ieșire care sunt conectate la mufele vizibile pe panoul didactic. Noi vom conecta la acest panou, cu ajutorul unor cabluri Microcontrolerul prezentat în următorul capitol, acesta va face conversia dintre semnalele electronice ale panoului didactic și le va transforma în semnale digitale care vor fi trimise către tabletă prin conexiunea USB.
Tableta, la fel, va trimite semnale digitale la Microcontroler, acesta transformându-le în semnale electronice, care pot fi citite de către PLC și interpretate.
Panoul didactic ajută mult la identificarea pinilor corespunzători de pe PLC și modulele utilizate, aceste module fiind deja conectate intre ele prin cabluri pentru a cuminica.
Acest panou didactic dispune pe pinii “ANALOG INPUTS” la care sunt conectate generatoare de tensiune care pot fi activate prin punerea pe poziția Sus a comutatorului de sub potențiometrul dorit sa fie activat. Acest lucru ne ajuta mai departe pentru a controla viteza de referință la care motorul va fi ținut constant. De asemenea dacă comutatorul este pus în poziția Jos putem trimite o tensiune cu ajutorul altui generator extern, noi vom conecta ulterior Microcontrolerul.
4.1.3. Elemente de bază ale modulelor unitate centrală
Cu o tensiune de alimentare integrată (prin conexiunea de 24V) și intrările și ieșirile integrate, modulul unitate centrală CPU S7-1200 este gata de funcționare, fără alte componente suplimentare. Pentru comunicația cu dispozitivul de programare, modulul unitate centrală CPU este echipat cu un port TCP/ IP integrat.
Printr-o rețea Ethernet, modulul unitate centrală CPU este capabil să comunice cu dispozitive de tip panou operator HMI (human machine interface) sau cu alte module CPU.
Conexiunea de alimentare de 24V
Bloc terminal de conexiuni pentru cablarea cu procesul (sub clapeta de protecție)
LED-uri de stare a intrărilor / ieșirilor integrate și regimurilor de operare a modulului unitate centrală CPU
Conexiune TCP/IP (în partea de a CPU)
Cardul de memorie SIMATIC (MC) stochează programul , datele, date de sistem, fișiere și proiecte. Acesta poate fi folosit pentru următoarele:
– Transferul unui program la mai multe module unitate centrală CPU
– Actualizarea firmware-ului modulelor unitate centrală CPU, al modulelor de semnale SM și al modulelor de comunicație CM
4.2. Microcontrolerul PIC18F4550
Acest microcontroler are un convertor A/D 10 biți cu 13 canale, 4 timer, unul pe 8 biți și 3 pe 16 biți și 2 comparatoare. Datorită cantității mari de memorie RAM și de memorie de program FLASH îl fac ideal pentru aplicațiile integrate de control și monitorizare, aplicații ce necesită des conexiuni prin intermediul interfeței USB, pentru upload/download sau actualizări software.
Inima Microcontrolerului este cipul PIC18F4550, acest cip este un microcontroler care are rolul de citire a unor tensiuni și generare a unor tensiuni.
In proiectul actual modulul are disponibile:
8 porturi de intrare digitale
5 porturi de intrare analog, prin care se poate citi o tensiune între 0V și +5V
8 porturi de ieșire digitale
2 porturi de ieșire analog (PWM) prin care putem trimite o tensiune de 0V – +5V
Pentru realizarea schemelor s-a folosit softul Eagle PCB 7.2.0, acesta fiind un program software care este distribuit gratis. Linkul către pagina de descărcare poate fi găsit la Bibliografie.
Pentru programarea microcontrolerului s-a folosit limbajul C++ care a fost scris și compilat cu ajutorul softului furnizat de producătorul MICROCHIP, acest soft se numește MPLAB-X și s-a folosit versiunea gratis, care are anumite limitări și nu optimizează codul la fel de mult ca și versiunea plătita a aceluiași program.
4.2.1. Placa de bază care conține microcontrolerul PIC18F4550
Placa pe care sunt situate componentele de bază prin care funcționează modulul este destul de simplă și arată cum se poate vedea în imaginea alăturată.
Placa de bază conține un led prin care se poate vedea dacă conexiunea la USB este activă, în standby sau inactivă. Mai are un buton de reset prin care se poate aduce microcontrolerul la starea inițială. Rezonatorul de frecvență este un cristal de cuarț de 20MHz care permite funcționarea procesorului din microcontroler la o frecvență de 20MHz.
Schema electronică si PCB-ul:
Această schemă a fost realizată cu ajutorul programului Eagle PCB care este un software freeware de proiectare a circuitelor electronice, el este destul de ușor de folosit și poate fi găsit pe internet printr-o căutare Google. De asemenea îl puteți găsi în secțiunea Bibliografie, este trecut ca un link către site-ul software-ului
La această placă se conectează, cu ajutorul unui cablu panglică, unul din modulele de conectare în funcție de echipamentul dorit, echipamentul de comandă și control. Noi în acest proiect avem la dispoziție două moduri de funcționare modul de testare și modul de simulare a unui motor electric în care comanda se face cu ajutorul automatului SIMATIC S7-1200.
4.2.2. Placa de testare
Placa de testare are ca și scop, după cum îi zice și numele, testarea funcționări corecte a sistemului. Cu ajutorul acestei plăci se pot verifica toate porturile de intrare/ieșire.
Placa conține următoarele porturi de intrare/ieșire:
8 butoane care sunt conectate la cele 8 intrări digitale ale Microcontrolerului.
8 leduri care sunt conectate la cele 8 ieșiri digitale ale Microcontrolerului
5 potențiometre prin care trimitem o tensiune de la 0V la +5V către cele 5 porturi de intrare ale Microcontrolerului
2 leduri care își modifica intensitatea luminoasă în funcție de tensiunea care se primește de la cele 2 porturi de ieșire analogice ale Microcontrolerului, acest lucru se va face cu ajutorul unui principiu de Power With Modulation (PWM)
Schema electronică a plăcii si PCB-ul realizate cu ajutorul softului Eagle PCB se pot vedea în imaginile alăturate. Cele 8 butoane din partea de jos vor acționa cele 8 intrări digitale ale Microcontrolerului.
Piesele albastre reprezintă potențiometre care prin varierea lor se va varia o tensiune care este interpretata pe cei 5 pini de intrare analogică ai Microcontrolerului.
Ledurile de sus reprezintă ieșirile Microcontrolerului, cele 2 din partea stângă fiind cele analogice, celelalte 8 din partea dreaptă reprezentând cele digitale.
Aceasta placă are ca scop testarea aplicației software care este realizată pe tabletă pentru a vedea daca informația dorită ajunge și elementele din tabletă se comportă cum au fost proiectate.
4.2.3. Placa de conectare cu PLC-ul SIMATIC S7-1200
Aceasta placă conține conexiunile necesare conectării automatului SIMATIC S7-1200 la placa principală prin cablul panglică.
Pe această placă, s-a ales pentru protecția împotriva setării accidentale ale automatului care poate furniza o tensiune de până la +24V, folosirea unei protecții realizate cu regulatorul de tensiune L78S05CV, care acceptă până la +32V și tensiunea de ieșire nu poate fi mai mare de +5V.
Schema electronică și PCB-ul realizat cu ajutorul softului Eagle PCB
Este pus pe placă un conector, acest conector se poate vedea în schema de mai sus și este numit JP1, la care ne putem atașa cu cabluri pentru fiecare din pinii Microcontrolerului, acesta fiind legat prin cablu panglică conectat la mufa JP2. Regulatoarele de tensiune au fost adăugate pentru a proteja PLC-ul și Microcontrolerul de posibile erori prin care putem deteriora echipamentele dacă avem o sarcină mai mare decât cea admisă. De asemenea mufa JP1 a fost adăugată pe a ne putea conecta ușor la orice pin al Microcontrolerului.
5. Descriere Software
5.1. Sistemul de automatizare SIMATIC S7-1200
5.1.1. Mediul de programare TIA PORTAL V11
TIA Portal V11 este mediul de programare pentru sistemul de automatizare – SIMATIC S7-1200 pe care l-am utilizat la realizarea lucrării de licență.
TIA Portal V11, permite utilizarea următoarelor funcții pentru a automatiza o instalație:
Configurarea și parametrizarea hardware
Definirea comunicației
Programarea
Testarea, punerea în funcțiune și service-ul cu funcțiile de operare / diagnosticare
Elaborarea documentației
Generarea ecranelor de afișare pentru panourile de operare de bază SIMATIC
Conectarea la CPU prin conexiune TCP/IP și revenirea la setările inițiale de fabrică
Pentru a programa automatul programabil SIMATIC S7-1200 de la PC, PG (echipament de programare SIEMENS) sau un laptop, este nevoie de o conexiune TCP / IP între cele două echipamente.
Pentru a comunica unul cu altul, este nevoie , de asemenea, ca adresele calculatorului și automatului programabil SIMATIC S7-1200 să corespundă.
Setarea adresei IP a calculatorului se realizează astfel:
1. Din meniul 'System control’, se apelează 'Network connections’. Apoi, se selectează 'Properties’ ale conexiunii LAN (→ Start → Settings → System control
→ Network connections→ Local Area Connection → Properties)
2. Se selectează 'Properties’ din cadrul 'Internet Protocol (TCP/IP)’ (→ Internet Protocol (TCP/IP) → Properties)
3. Acum se poate seta ’IP address’ și ’Subnet screen form’, iar apoi se pot confirma cu ’OK’ (→ Use the following IP address → IP address: 192.168.0.99 → Subnet screen form 255.255.255.0 → OK → Close)
Comunicația pe rețeaua Ethernet între calculatorul PC pe care rulează TIA Portal și automatul programabil S7-1200:
Adresa MAC:
Adresa MAC conține o parte fixă și o parte variabilă. Partea fixă ("Basic MAC Address") identifică producătorul (Siemens, 3COM, …). Partea variabilă a adresei MAC diferențiază diferitele posturi Ethernet și trebui să fie unică ( la nivel mondial) pentru fiecare echipament. Fiecare modul are imprimată o adresa MAC specificată de producător.
Gama de valori pentru adresa IP:
Adresa IP constă din 4 numere zecimale din intervalul de valori 0 la 255, separate între ele prin puncte. De exemplu, 141.80.0.16
Gama de valori pentru masca de subrețea:
Această mască este utilizată pentru a recunoaște dacă un post sau adresă IP aparține subrețelei locale, sau pot fi accesată numai prin intermediul unui router.
Masca de subrețea este format din patru numere zecimale din gama 0 la 255, separate între ele prin puncte. De exemplu, 255.255.0.0
În reprezentarea binară, cele 4 numere zecimale ale măștii de subrețea trebuie să conțină, începând din stânga o serie continuă de valori "1", iar începând din dreapta o serie continuă de valori "0".
Valorile "1", specifică zona adresei IP pentru numărul de rețea. Valorile "0", specifică zona a adresei IP pentru adresa de post din subrețea.
Exemplu: Valori corecte:
255.255.0.0 zecimal = 1111 1111.1111 1111.0000 0000.0000 0000 binar
255.255.128.0 zecimal = 1111 1111.1111 1111.1000 0000.0000 0000 binar
255.254.0.0 zecimal = 1111 1111.1111 1110.0000 0000.0000.0000 binar
Valoare greșită:
255.255.1.0 zecimal = 1111 1111.1111 1111.0000 0001.0000 0000 binar
Gama de valori pentru adresa de gateway (Router):
Adresa constă din 4 numere zecimale din intervalul de valori 0 la 255, separate între ele prin puncte. De exemplu, 141.80.0.1.
Relația dintre adresa IP, adresa router și masca de subrețea: Adresa IP și adresa gateway trebuie să difere doar în pozițiile ce se află în dreptul valorilor "0" din masca de subrețea.
Exemplu:
S-au selectat următoarele adrese : pentru masca de subrețea 255.255.255.0, pentru adresa IP 141.30.0.5 și adresa router 141.30.128.1.
Adresa IP și adresa de gateway trebuie să aibă o valoare diferită numai în cel de al 4-lea număr zecimal. Dar, în exemplul nostru, cele două adrese diferă și în cel de al 3-lea număr zecimal.
Asta înseamnă că, în exemplul nostru trebuie să facem una din următoarele schimbări:
– Masca de subrețea să devină : 255.255.0.0 sau
– Adresa IP să fie: 141.30.128.5 sau
– Adresa gateway să fie: 141.30.0.1
Adresa IP a automatului programabil SIMATIC S7-1200 se setează astfel:
4. Se selectează ’Totally Integrated Automation Portal’ prin dublu click (→ Totally Integrated Automation Portal V11)
5. Apoi se selectează ’Project View’ din partea stânga jos a ecranului. (→ Project view)
6. Apoi, în meniul de navigație tip proiect, selectăm în ’Online accesses’, placa de rețea care a fost deja instalată în prealabil. Dacă aici se face clic pe ’Update accessible stations’, va fi prezentată adresa MAC a automatului programabil SIMATIC S7-1200 conectat la calculator. Se selectează ’Online & Diagnosis’. (→ Online accesses → Network Connection → Update accessible stations → MAC= → Online & Diagnosis)
Notă: Dacă pentru unitatea centrală CPU a automatului programabil conectată la calculator, s-a setat în prealabil o adresă IP, în loc de adresa MAC va apare această adresă.
7. În submeniul ’Functions’ se va putea selecta ’Assign IP address’. Aici se va introduce la ’IP address’ adresa IP a automatului iar la ’Subnet screen form’ masca de subrețea. După click pe ’Assign IP address’, această nouă adresă va fi atribuită automatului programabil SIMATIC S7-1200 (→ Functions → Assign IP address → IP address: 192.168.0.1 → Subnet screen form: 255.255.255.0 → Assign IP address)
8. În submeniul ’Functions’, se selectează ’Reset to factory settings’. Se mențin setările de până acum prin selectarea ’Keep IP address’ și se apasă pe ’Reset’. (→ Functions → Reset to factory settings → Retain IP address → Reset)
9. Se confirmă solicitarea de reset dacă se vrea revenirea la setările din fabrică cu butonul ’OK’ (→ OK)
5.1.2. Software-ul de comandă și control (PID-ul)
Într-un sistem de reglare după eroare (abatere), regulatorul îndeplinește rolul elementului de comandă, de decizie. Regulatorul primește la intrare două semnale: semnalul de referință (numit și Setpoint), care exprimă procentual valoarea dorită a mărimii reglate (de ieșire a procesului) și semnalul de măsură, generat de traductorul mărimii reglate sau de ansamblul traductor-adaptor.
In urma procesării celor două semnale după un algoritm convenabil, dependent de comportamentul dinamic al procesului reglat, regulatorul elaborează semnalul de comandă a elementului de execuție, prin intermediul căruia se intervine asupra procesului reglat pentru a aduce mărimea reglată la o valoare cât mai apropiată de valoarea referinței.
La trecerea sistemului de reglare din regimul MANUAL în regimul AUTOMAT, algoritmul de comandă al regulatorului înlocuiește raționamentul, judecata, logica operatorului uman. În funcție de natura fizică a semnalelor de intrare și de ieșire, regulatorul poate fi: electronic, pneumatic, hidraulic sau mecanic.
In funcție de forma semnalelor procesate, regulatoarele pot fi continue (analogice), discrete (numerice), bipoziționale sau tripoziționale. Cele mai performante și mai frecvent utilizate sunt, evident, regulatoare electronice numerice. Acum sa începem implementarea în TIA Portal v11 software-ul care va controla viteza cu care se rotește roata secundara în simulatorul software de pe Tableta.
Configurația proiectului din cadrul softului TIA Portal, trebuie sa fie cea care o avem în mediul fizic, pe panoul didactic din laborator. Această configurație trebuie reprodusă în soft, adăugând echipamentele necesare extinderii porturilor, prin simpla tragere din partea dreaptă a echipamentelor dorite în fereastra din mijloc.
Pasul următor este sa adăugam un nou bloc din meniu, apăsând pe PLC_1->Program blocks->Add new block. Se selectează “Cyclic interupt” și se adaugă. Acest lucru este realizat pentru ca codul să fie executat în cadrul unui interrupt, acesta fiind ciclic.
Din partea dreaptă a ecranului se selectează din secțiunea “Tehnology” elementul “PID controller” și se adaugă în mijlocul imaginii, în secțiunea unde se va executa acel bloc software.
Tot din partea dreaptă, din secțiunea “Basic instructions” se adaugă un bloc de tip DIV într-o nouă rețea numită „network2”.
Blocul PID se va configura cu tag-urile necesare ca în imaginea de mai jos:
Acest lucru se poate realiza prin click dreapta de mouse pe blocul PID și se apasă “Review tags”, după această operațiune va apărea imaginea de mai sus cu valorile implicite. După ce am setat numele lor, trebuie setate tipurile lor, pentru „Setpoint” o să punem ca ia o valoare din „Global memory”, și aceasta fiind un întreg, pentru „Input” vom seta un „Global input” și pinul de intrare „%IW112”, pentru „Output” vom seta un „Global output” și pinul de ieșire ”%QW112”
Blocul DIV se va configura cu tag-urile necesare ca în imaginea de mai jos, acest lucru se va face similar ca blocul PID.
Pentru „Setpoint” o să punem ca ia o valoare din „Global memory”, acest rând trebuie sa fie identic cu cel de la PID și să aibă același nume pentru a trimite valoarea în aceeași adresă de memorie a PLC-ului.
Pentru „Setpoint POT” vom seta un „Global input” și pinul de intrare „%IW114”, acesta reprezintă potențiometrul și poate lua valoarea de la 0 la 29600 unde la 29600 avem +10V.
De asemenea pentru blocul DIV trebuie setat numărul 296 pe IN2 pentru a avea o valoare finală intre 0 și 100 care este transformată din valoare de la 0 la 29600 obținută prin citirea valorii potențiometrului.
Această valoare este trimisă către blocul PID ca fiind „Setpoint” și va seta viteza cu care motorul trebuie să se rotească.
Se va seta modul de operare al PID-ului ca fiind “speed” și intrarea/ieșirea ca fiind PER(Analog)
După configurare blocurile programate trebuie să arate ca în imaginea de mai jos:
Aceștia sunt toți pașii necesari programării PLC-ului SIMATIC S7-1200 folosind software-ul TIA PORTAL v11 pentru realizarea proiectului de licență. Toate blocurile folosite se pot găsi în lista din partea dreaptă in secțiunile menționate anterior.
5.2. Software pentru microcontrolerul PIC18F4550
5.2.1. Schema bloc
Mai jos se poate vedea schema logică de implementare și fluxul informației.
Programul începe cu funcția Main() unde se apelează în primul rând metodele de inițializare, aceste metode practic asociază și inițializează pinii folosiți și configurați în fișierele de configurare header.
InitializeSystem() va inițializa sistemul, USBDeviceInit() va inițializa setările pentru portul USB, unde USBDeviceAttach() va inițializa procedurile de conectare la portul USB, acesta fiind setat in modul client, el poate de asemenea să fie setat ca sa funcționeze in modul host.
Tot în Main() avem bucla principală de execuție care are rolul de a atașa și deconecta USB-ul și de asemenea se apelează metoda DeviceTasks(), această metodă fiind cea care citește/scrie în microcontroler valorile dorite.
Metoda InitializeSystem() de fapt apelează în funcție de starea conexiuni la USB diversele componente software care fiecare se ocupă cu un alt lucru. Codul metodei se poate vedea mai jos.
void InitializeSystem( SYSTEM_STATE state ){
switch(state){
case SYSTEM_STATE_USB_START:
InitializeStatusLED();
InitializeDataINPins();
InitializeDataOUTPins();
InitializeAnalogINPins();
InitializeAnalogOUTPins();
break;
}
}
Fiecare metodă în parte va inițializa diversele parți ale microcontrolerului. O să dăm doar un exemplu din listă, acesta fiind InitializeDataINPins(), pentru restul codul este similar, numai ca vor avea alți pini inițializați cu alte valori, acest lucru se poate vedea și în codul sursă.
//set all pins to input
void InitializeDataINPins(void){
IN_D1_TRIS = 1;
IN_D2_TRIS = 1;
IN_D3_TRIS = 1;
IN_D4_TRIS = 1;
IN_D5_TRIS = 1;
IN_D6_TRIS = 1;
IN_D7_TRIS = 1;
IN_D8_TRIS = 1;
}
Toate constantele de mai sus au fost definite în prealabil în secțiunea de configurare cu pinii fizici corespunzători de pe microcontroler.
Funcția Main() reprezintă inima oricărui program, aceasta se poate vedea mai jos.
void main(void){
InitializeSystem(SYSTEM_STATE_USB_START);
USBDeviceInit();
USBDeviceAttach();
while(1){
/* If the USB device isn't configured yet, we can't really do anything
* else since we don't have a host to talk to. So jump back to the
* top of the while loop. */
if( USBGetDeviceState() < CONFIGURED_STATE ){
/* Jump back to the top of the while loop. */
continue;
}
/* If we are currently suspended, then we need to see if we need to
* issue a remote wakeup. In either case, we shouldn't process any
* keyboard commands since we aren't currently communicating to the host
* thus just continue back to the start of the while loop. */
if( USBIsDeviceSuspended() == true ){
/* Jump back to the top of the while loop. */
continue;
}
//Application specific tasks
DeviceTasks();
}//end while
}//end main
5.2.2. Modul de funcționare
In momentul în care modulul de simulare software este conectat prin USB, atunci se execută codul din bucla principală. O dată la 50ms softul de pe Tabletă va trimite o serie de comenzi prin USB, acestea fiind de doua tipuri, de citire și de scriere.
Cele 4 comenzi sunt următoarele:
Comanda de citire pentru pinii de intrare analog, definită de constanta COMMAND_AIN. Când aceasta comandă este primită de Microcontroler, acesta va citi următorul BYTE primit, reprezentând pinul analog care se dorește să fie citit. După citire Microcontrolerul va trimite 2 bytes la Tabletă cu valoarea pentru pinul dorit să fie citit.
Comanda de scriere pentru pinii de ieșire analog, definită de constanta COMMAND_AOUT. Când această comandă este primită atunci Microcontrolerul va interpreta următorii 3 bytes primiți de la Tabletă, primul fiind pinul care se dorește a fi scris, al doi-lea și al trei-lea se vor compune într-un DWORD care este valoarea setată în Microcontroler pentru a fi trimisă ca o tensiune automatul Siemens.
Comanda de citire pentru pinii de intrare digitali, definită de constanta COMMAND_DIN. Când această comandă este primită de către modul atunci el va citi starea pinului digital (butonului) care se dorește și va trimite această valoare la Tabletă.
Comanda de citire pentru pinii de ieșire digitali, definită de constanta COMMAND_DOUT. Când această comandă este primită de către modul atunci el va scrie starea primită către pinul digital și acesta va avea +5V sau 0V în funcție de starea care este primită de la Tabletă.
Acesta transformare din volți în date, valori care pot fi interpretate de către un software este realizată cu ajutorul acestui modul și trimise la Tabletă care le va interpreta și în funcție de valorile primite va acționa în consecința.
O parte din codul sursa se poate vedea mai jos, în aceasta se distinge modul prin care se ia decizia comenzii curente și se formează buffer-ul care va fi trimis la USB.
void DeviceTasks(){
//Check if we have received an OUT data packet from the host
if(HIDRxHandleBusy(USBOutHandle) == false){
//We just received a packet of data from the USB host.
//Check the first uint8_t of the packet to see what command the host
//application software wants us to fulfill.
switch(ReceivedDataBuffer[0]){ //Look at the data the host sent, to see what kind of application specific command it sent.
case COMMAND_DOUT:
{
DATA_OUT data_out;
switch(ReceivedDataBuffer[1]){
case 1: data_out = OUT_D1; break;
case 2: data_out = OUT_D2; break;
case 3: data_out = OUT_D3; break;
case 4: data_out = OUT_D4; break;
case 5: data_out = OUT_D5; break;
case 6: data_out = OUT_D6; break;
case 7: data_out = OUT_D7; break;
case 8: data_out = OUT_D8; break;
}
switch(ReceivedDataBuffer[2]){
case COMMAND_DOUT_ON: OUT_On(data_out); break;
case COMMAND_DOUT_OFF: OUT_Off(data_out); break;
case COMMAND_DOUT_TOGGLE: OUT_Toggle(data_out); break;
}
}
break;
case COMMAND_DIN:
//Check to make sure the endpoint/buffer is free before we modify the contents
if(!HIDTxHandleBusy(USBInHandle)){
DATA_IN data_in;
switch(ReceivedDataBuffer[1]){
case 1: data_in = IN_D1; break;
case 2: data_in = IN_D2; break;
case 3: data_in = IN_D3; break;
case 4: data_in = IN_D4; break;
case 5: data_in = IN_D5; break;
case 6: data_in = IN_D6; break;
case 7: data_in = IN_D7; break;
case 8: data_in = IN_D8; break;
}
ToSendDataBuffer[0] = COMMAND_DIN;
if(GetIN(data_in) == false){
ToSendDataBuffer[1] = 0x01; //In data is not pressent
}else{
ToSendDataBuffer[1] = 0x00; //In data is pressent
}
//Prepare the USB module to send the data packet to the host
USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ToSendDataBuffer[0],64);
}
break;
case COMMAND_AIN:
//Check to make sure the endpoint/buffer is free before we modify the contents
if(!HIDTxHandleBusy(USBInHandle)){
uint16_t value;
AIN_CHANNEL analog_in;
switch(ReceivedDataBuffer[1]){
case 1: analog_in = AIN_CHANNEL1; break;
case 2: analog_in = AIN_CHANNEL2; break;
case 3: analog_in = AIN_CHANNEL3; break;
case 4: analog_in = AIN_CHANNEL4; break;
case 5: analog_in = AIN_CHANNEL5; break;
}
value = AIN_Read10bit(analog_in);
ToSendDataBuffer[0] = COMMAND_AIN; //Echo back to the host the command we are fulfilling in the first uint8_t.
ToSendDataBuffer[1] = (uint8_t)value; //LSB
ToSendDataBuffer[2] = value >> 8; //MSB
//Prepare the USB module to send the data packet to the host
USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ToSendDataBuffer[0],64);
}
break;
case COMMAND_AOUT:
{
uint16_t value;
AOUT_CHANNEL analog_out;
switch(ReceivedDataBuffer[1]){
case 1: analog_out = AOUT_CHANNEL1; break;
case 2: analog_out = AOUT_CHANNEL2; break;
}
value = ReceivedDataBuffer[2] | ReceivedDataBuffer[3] << 8;
setAOut(analog_out, value);
}
break;
}
//Re-arm the OUT endpoint, so we can receive the next OUT data packet
//that the host may try to send us.
USBOutHandle=HIDRxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ReceivedDataBuffer, 64);
}
}
5.2.3. Fișiere sursă și rolul lor
Aplicația conține mai multe directoare structurate astfel:
Header Files/framework/usb – Acest folder conține fișierele de configurare ale librăriei de comunicare USB care a fost folosită și descărcată de pe site-ul microchip.com
Header Files/app – Acest folder conține fișierele de configurare pentru Microcontroler
Source Files/framework/usb – Acest folder conține fișierele sursă ale librăriei de comunicare USB care a fost folosită și descărcată de pe site-ul microchip.com
Source Files/app – Acest folder conține fișierele sursa pentru Microcontroler
Header Files/app
a_out.h – În acest fișier se configurează pinii de ieșire PWM
d_out.h – În acest fișier se configurează pinii de ieșire digitală
a_in.h – În acest fișier se configurează pinii de intrare analog
d_in.h – În acest fișier se configurează pinii de intrare digitală
status.h – În acest fișier se configurează pinul ledului de status de pe placa principală
Source Files/app
a_out.c – În acest fișier se inițializează pinii și se definește funcția de setare a lor, pentru pinii de ieșire analog
d_out.c – În acest fișier se inițializează pinii și se definește funcția de setare a lor, pentru pinii de ieșire digitali
a_in.c – În acest fișier se inițializează pinii și se definește funcția de setare a lor, pentru pinii de intrare analog
d_in.c – În acest fișier se inițializează pinii și se definește funcția de setare a lor, pentru pinii de intrare digitali
device.c – Acesta conține codul sursa care face conversia din stările hardware în stările software
status.c – Acest fișier conține codul de control al ledului ce status al plăcii principale, care evidențiază conexiunea la USB
main.c – Acest fișier inițializează și controlează conexiune la USB cât și bucla principala a programului
system.c – Acest fișier conține metodele de inițializare ale sistemului
usb_descriptors.c – Acest fișier conține metodele de inițializare și setare a conexiunii la UBS
Pentru implementarea software-ului a fost folosit un editor/compilator numit MPLAB X IDE v2.25, acesta fiind disponibil de pe microchip.com într-o variantă gratis. Codul a fost scris în limbajul de programare C++. Există și o variantă plătită a acestui soft care va compila codul mult mai eficient.
5.3. Tableta cu sistemul de operare Android
5.3.1. Generalități
Software-ul de pe Tabletă este de fapt cea mai complexă componentă a proiectului, el realizează simularea, în timp real, folosind forțe de frecare, vectori, inerție și multe alte componente fizice furnizate de librăria Box2D și AndEngine.
Acest software este realizat modular și poate avea mai multe simulări disponibile. În acest proiect de licență au fost implementate doar două, una pentru testarea sistemului, a doua pentru simularea unui motor electric și ce se întâmplă cu automatul Siemens când acționăm o frâna asupra unei roți.
Simularea fizică
În dezvoltarea de jocuri, "fizica" este colecția de efecte care imită legile fizicii din lumea reală. Fizica nu intră în fiecare tip de joc, desigur. De exemplu, în general, nu va fi nevoie de fizică dacă dezvoltăm un joc pe o tablă. Alte jocuri sunt aproape în întregime bazate pe fizică, cu rachete de diferite tipuri urmărind arce naturale, spărgându-se în grămezi de obiecte care apoi se rup sau cad în jos sub influența gravitației. După cum vom vedea, un motor de fizică foarte complex pentru utilizarea în jocurile noastre este disponibil ca o extensie a AndEngine. Vom investiga acest motor și instrumentele conexe, iar apoi vom construi un pic de fizică pe baza de gamelet pentru a spori cunoștințele de bază pentru realizarea proiectului de licență. Nu vom fi nici pe departe aproape de a aprofunda toate lucrurile pe care ni le furnizează motorul de simulare fizică, dar vom înțelege cum funcționează.
În ilustrarea de mai jos, jucătorul poate lansa butuci de lemn către obiectele din joc atingând, trăgând sau dând drumul. Ideea este de a obține capetele de vampir să atingă solul.
Motorul de simulare fizică Box2D
Motorul de fizică utilizat de AndEngine se numește Box2D. Motorul Box2D a fost scris inițial în C++ de către Erin Catto, ca parte a unui tutorial de motoare pentru simulare fizică. Acesta a fost extins considerabil, adaptat în o serie de alte limbaje și în mai multe motoare de jocuri 2D.
Acum vom explora doar o mică parte din Box2D, dar informația și exemplele prezentate ar trebui să vă dea un avans în înțelegerea acestuia. Vom descrie ceea ce trebuie să știți pentru a crea lumi bazate pe Box2D în AndEngine, dar pentru o detaliere mai completă, vă recomandăm Manualul Box2D, care ar trebui să se găsească la următoarea adresă: http://www.box2d.org/manual.html
Concepte Box2D
Pentru a vorbi despre un motor de fizică, cum ar fi Box2D, trebuie mai întâi să definim câțiva termeni, acești termeni sunt definiți si mai detaliat în Manualul Box2D.
Unități
Simularea fizicii pe care Box2D o efectuează este sensibilă la unitățile care le folosim pentru masă, viteză și alte mărimi. Box2D este reglat pentru MKS (metru-kilogram-secundă) de unități și este proiectat pentru a simula obiecte "de dimensiuni normale", așa cum acestea interacționează. În acest caz, "normal de dimensiuni" înseamnă obiecte în mișcare între 0.1 și 10 metri lungime și obiecte statice de 50 de metri lungime. Vom vedea mai târziu că AndEngine oferă o constantă, PIXEL_TO_METER_RATIO_DEFAULT, pe care o putem folosi pentru a traduce între pixeli și coordonatele lumii fizice. Dacă utilizați unități pixel direct cu Box2D, simulările rezultate nu vor arăta realist.
Lumea
Box2D ne permite să construim lumi virtuale unde corpuri se comportă la fel ca obiectele fizice care le întâlnim în viața reală. O lume Box2D este formată din corpuri, puncte fixe, articulații și constrângerile care constituie o simulare fizică a acestei lumi.
Corp rigid
Corpurile sunt baza obiectelor de simulare în Box2D. Ele au doar câteva caracteristici proprii, dar pot lua atribute fizice mai complexe prin asocierea cu forme, puncte fixe și constrângeri, așa cum este descris mai târziu în această secțiune. Restricția implicită pe care Box2D o asociază pe corpuri este că acestea sunt toate corpuri rigide, ceea ce înseamnă că formele lor nu devin distorsionate. Pentru a cita din Manualul Box2D, un corp rigid este:
O bucată de materie care este atât de puternică încât distanța între două bucăți de materie de pe bucată este complet constantă . Ele sunt dure ca un diamant .
Corpurile au un tip care poate fi oricare din următoarele trei valori:
Static: Corpuri care sunt în mod normal fixate în loc. Utilizatorul poate deplasa aceste corpuri, dar acestea nu sunt mutate în cadrul simulării fizicii. Corpuri statice acționează ca și cum ar avea masă infinită (reprezentat de o masă zero, atunci când le-am creat) și se ciocnesc doar cu corpurile dinamice.
Kinematic: Corpuri care se mișcă numai în temeiul vitezei lor. Aceste corpuri nu fac parte din simularea fizică și nu răspund la forțe. De asemenea, ele se comportă ca și cum ar avea masă infinită și se ciocnesc doar cu organismele dinamice.
Dynamic: În mișcare, corpuri simulate integral într-o lume fizică. Acestea au întotdeauna o masă finită, non-zero și se pot ciocni cu alte corpuri statice, cinematice, de asemenea și cu corpurile dinamice. Dacă încercați să setați masa unui corp dinamic la zero, acesta este resetat automat la 1 kilogram.
Forme
Box2D acceptă două lucruri de bază care aproximează forma pentru corpurile reale și anume, un cerc și un poligon. Când vom crea un corp Box2D, în mod normal, ne asociem o formă cu el printr-un dispozitiv. Când Box2D simulează fizica corpurilor care interacționează, se folosește forma corpului pentru a determina când apar coliziuni.
Puncte de fixare
Corpurile și formele devin asociate prin intermediul unui punct de fixare. În plus față de oferirea unei forme corpului, un punct de fixare prevede valori folosite pentru densitate, elasticitate și frecare. Aceleași valori de fixare sunt de obicei folosite de mai multe corpuri, așa că cel mai simplu e să le definim o dată și prin reutilizarea acestora vom crea alte corpuri.
Constrângeri
O constrângere împiedică un corp să se miște într-o anumită direcție. Un corp fără restricții în 2D are într-adevăr trei grade de libertate: x, y și rotație. Constrângerile sunt folosite pentru a elimina unul sau mai multe dintre aceste grade de libertate.
Legătură
În Box2D , o legătură este o constrângere care leagă două corpuri împreună. Articulațiile pot avea limite (cum ar fi un cot, care nu se poate îndoi înapoi) și motoare, care pot conduce mișcarea articulației. Box2D suportă legături de revoluție, prismatice, de distanță, scripete, mouse-ul ,liniare și articulațiile de sudură, toate acestea sunt explicate în detaliu în Manualul Box2D .
Senzor
Poate jocul are nevoie de un corp care detectează coliziuni, dar nu răspunde la ele. Senzorii satisfac această nevoie și vom vedea că puteți declara orice organism să fie un senzor.
Glonț
Box2D caută coliziuni între corpurile dinamice și statice prin scanarea mișcării corpurilor dinamice dintre cadrele de simulare (referite ca o detecție a coliziunilor continuă). Această practică se asigură că un corp dinamic nu poate trece printr-un corp static între cadre.
Dacă mPhysicsWorld este lumea care ați creat-o, atunci ar trebui să utilizați această linie:
mPhysicsWorld.setContinuousPhysics(true);
AndEngine și Box2D
Fizica este o extensie a motorului AndEngine. Acesta trebuie să fie descărcată și instalată separat. AndEngine folosește librăria libgdx JNI, care furnizează o interfață foarte completă la baza bibliotecii C++ Box2D; Mario Zech-ner este dezvoltatorul principal pentru libgdx. AndEngine oferă un API care face ușor de utilizat interfața libgdx într-un joc bazat pe AndEngine.
Box2D API
Extensia pentru fizică Box2D adaugă 16 clase la AndEngine. Acesta adaugă, de asemenea, clasele Box2D înșiși, care fac parte din biblioteca libgdx. Pentru dezvoltarea de jocuri, trebuie să știm despre doar trei clase:
PhysicsWorld: care reprezintă lumea Box2D
PhysicsFactory: care ne ajută să generam corpuri și puncte fixe Box2D
PhysicsConnector: care conectează corpuri Box2D cu entități AndEngine
Crearea de lumi: PhysicsWorld
Putem folosi clasa PhysicsWorld pentru a crea lumea fizică în care are loc acțiunea noastră. După ce am creat-o, o adăugăm la scena AndEngine astfel va fi afișată. Pentru aceasta există doi constructori :
PhysicsWorld(final Vector2 pGravity, final boolean pAllowSleep)
PhysicsWorld(final Vector2 pGravity, final boolean pAllowSleep, final int
pVelocityIterations, final int pPositionIterations)
Crearea de corpuri: PhysicsFactory
Acum, că avem o lume creată, putem începe crearea corpurilor, formelor, punctelor de fixare și îmbinărilor pentru a crea obiectele din modelul nostru. AndEngine oferă clasa singleton PhysicsFactory pentru a facilita aceste sarcini. Noi nu trebuie să instanțiem PhysicsFactory; în schimb, AndEngine o instanțiază pentru noi. Noi o folosim în același mod în care am folosit și alte clase. PhysicsFactory definește următoarele metode pentru a crea corpuri fizice:
Body createBoxBody(final PhysicsWorld pPhysicsWorld, final IShape pIShape, final
BodyType pBodyType, final FixtureDef pFixtureDef)
Body createCircleBody(final PhysicsWorld pPhysicsWorld, final IShape pIShape, final
BodyType pBodyType, final FixtureDef pFixtureDef)
Body createLineBody(final PhysicsWorld pPhysicsWorld,
final Line pLine, final FixtureDef pFixtureDef)
Body createPolygonBody(final PhysicsWorld pPhysicsWorld, final IShape pIShape, final Vector2[]
pVertices, final BodyType pBodyType, final FixtureDef pFixtureDef)
Body createTrianglulatedBody(final PhysicsWorld pPhysicsWorld, final IShape pIShape, final
List<Vector2> pTriangleVertices, final BodyType pBodyType,
final FixtureDef pFixtureDef)
Fiecare din aceste metode au o variație cu un parametru adițional(ultimul parametru), float pPixelToMeterRatio, în cazul în care trebuie să setăm scalarea in funcție de pixel, diferită de valoarea implicită(32.0f).
Parametrii adiționali sunt următorii:
PhysicsWorld pPhysicsWorld: Lumea în care va fi corpul. De obicei, aceasta va fi lumea nou creată cu PhysicsWorld .
IShape pIShape or Line pLine: Forma pe care vrem să o atașăm la corp. Formele sunt doar forme geometrice, fie corpuri sau forme geometrice create cu ceva de genul „metoda AndEngine Dreptunghi”.
BodyType pBodyType: Parametrul în care noi vom spune ce tip de corp definim:
BodyType.StaticBody
BodyType.KinematicBody
BodyType.DynamicBody
FixtureDef pFixtureDef: Punctul de fixare pe care îl dorim sa îl folosim pentru corp.
TrianglulatedBody: Aici trecem o listă de noduri triunghi ca variabile Vector2: Lista < > Vector2 pTriangleVertices.
Crearea de puncte de fixare: PhysicsFactory
Clasa PhysicsFactory include, de asemenea metode care creează puncte de fixare pentru noi:
FixtureDef createFixtureDef(final float pDensity, final float pElasticity,
final float pFriction, final boolean pSensor)
FixtureDef createFixtureDef(final float pDensity, final float pElasticity,
final float pFriction, final boolean pSensor, final short pCategoryBits,
final short pMaskBits, final short pGroupIndex)
Parametrii din prima metodă sunt evidenți, cu excepția, poate, pentru boolean pSensor, care este opțional. Dacă acest parametru este inclus și adevărat, punctul de fixare este un senzor cum este definit anterior în secțiunea "Concepte Box2D".
PhysicsConnector
Clasa PhysicsConnector ne permite reducerea decalajului dintre entitățile AndEngine (cum ar fi corpurile) și organismele Box2D. În acest fel putem folosi toate „bunătățile” AndEngine, cum ar fi modificatoarele, pe obiecte combinate și Box2D va face simularea fizică pentru noi.
Exista patru constructori pentru PhysicsConnector:
PhysicsConnector(final IShape pShape, final Body pBody) PhysicsConnector(final IShape pShape,
final Body pBody, final float pPixelToMeterRatio)
PhysicsConnector(final IShape pShape, final Body pBody, final boolean pUdatePosition,
final boolean pUpdateRotation)
PhysicsConnector(final IShape pShape, final Body pBody, final boolean pUdatePosition,
final boolean pUpdateRotation, final float pPixelToMeterRatio)
Primii doi parametri în fiecare caz sunt doar de formă (Sprite) și corpul pe care dorim să îl conectăm. Rețineți că este necesară crearea și înregistrarea acesteia, chiar dacă este posibil să fi folosit Sprite ca formă atunci când ați creat corpul.
pPixelToMeterRatio este opțional; el are aceeași semnificație ca și pentru metodele PhysicsFactory, iar aceeași valoare implicită (32.0f). Cei doi parametri boolean specifică dacă Box2D va actualiza poziția și rotația corpului în simularea lumii fizice. De obicei, ne dorim aceste două caracteristici actualizate, astfel încât valorile implicite să fie adevărate.
5.3.2. Programul principal
Interfața principală conține meniul și codul necesar conectării prin USB al Microcontrolerului și să nu uităm de asemenea că în aceasta secțiune se inițializează și inima simulării pentru funcționarea motorului, AndEngine. Aceasta interfață este destul de simplă, modulară. Ea permite adăugarea de simulări noi foarte simplu prin definirea unei noi clase care va conține întreg codul pentru acea simulare. Prin aceasta reușim încapsularea codului.
Pentru scrierea acesteia a fost folosit limbajul de programare Java și ca IDE aplicația Eclipse, aceasta poate fi descărcată de pe site-ul developer.android.com.
In aceasta secțiune a aplicației se definesc și se implementează parametrii și metodele de comunicare cu Microcontrolerul. Aceste protocoale sunt standardizate pentru a fi folosite de către orice simulare adăugată ulterior.
Mai jos este schema bloc a aplicației software.
Această schemă este doar o vedere de ansamblu a obiectelor principale ale aplicației scrisă în Java de pe Tabletă. Prin urmărirea acestei scheme se poate observa modularitatea și de asemenea cum se poate adaugă o simulare nouă prin crearea unui nou obiect de tipul „Simulator[[Nume]]Activity”.
Funcționarea de bază este destul de simplă, în momentul în care este conectat un periferic la USB acesta este verificat, daca este Microcontrolerul atunci o conexiune este inițializată și la 50ms se vor trimite comenzi pentru citirea/scrierea valorilor dorite.
Metoda care este apelată la inițializarea aplicației este următoarea:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainActivity.thisObject = this;
this.showNoDeviceView();
}
Această metodă, showNoDeviceView(), va apela o alta care practic arată un mesaj către utilizator prin care i se spune să conecteze Microcontrolerul.
public void showNoDeviceView() {
setContentView(R.layout.activity_main);
SetupObject = null;
}
Mai jos este starea interfeței principale în momentul în care nu este conectată la Microcontroler.
Există un „listener” configurat care verifică conectarea oricărui periferic la portul USB, cum ar fi stick-uri USB, etc. Când acest periferic conectat la USB este Microcontrolerul, atunci va fi chemată prima simulare disponibilă, cea implicită, acesta fiind simularea de Debug.
Mai jos se poate vedea secvența de cod prin care se inițializează acest „listener”.
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(receiver, filter);
PendingIntent.getBroadcast(this,0,new Intent(getPackageName()+".USB_PERMISSION"),0);
După cum ziceam dacă perifericul atașat este Microcontrolerul atunci codul de mai jos va apela metoda showMainView() și va inițializa un obiect Device care va stoca starea tuturor pinilor de intrare/ieșire ale întregului sistem.
public Device loadDevice(UsbDevice device) {
// Check the USB device to see if it is our device
if ((device.getVendorId()==(int)0x04D8)&&(device.getProductId()==(int)0x003F)) {
showMainView();
return new Device(this.getApplicationContext(), device, handler);
}
return null;
}
După conectarea la Microcontroler va fi încărcată simularea de Debug, acesta este de fapt simularea pentru testarea pinilor de intrare/ieșire. Aceasta este prezentată în capitolul „Testarea parametrilor de intrare/ieșire”. Pentru a înțelege mai bine, stocarea informaților și comunicarea prin USB se face cu ajutorul acestui obiect Device(). Mai jos o să arătam proprietățile obiectului ca să exemplificăm cum sunt stocate informațiile si tipul fiecăreia dintre ele.
private final static byte DIN_Request = (byte) 0x81;
private final static byte DOUT_Request = (byte) 0x80;
private final static byte AIN_Request = (byte) 0x37;
private final static byte AOUT_Request = (byte) 0x38;
private final byte DIN[] = {0, 0, 0, 0, 0, 0, 0, 0};
private final byte DOUT[] = {0, 0, 0, 0, 0, 0, 0, 0};
private final int AIN[] = {0, 0, 0, 0, 0};
private final int AOUT[] = {0, 0};
private UsbDevice device = null;
private UsbManager manager = null;
private Handler handler = null;
private Boolean closeRequested = Boolean.valueOf(false);
private UsbDeviceConnection connection;
private UsbInterface intf;
private boolean connected = false;
De asemenea dacă am da exemplu pentru fiecare segment de cod pentru comunicare am umple câteva pagini, din acest motiv o să exemplific mai jos doar unul din cazuri și anume trimiterea unui pachet către Microcontroler prin care o să setam toți pinii de AOUT din el cu valorile aflate în tabletă.
synchronized (this.AOUT) {
for (int index = 1; index <= this.AOUT.length; index++) {
byte[] Packet = new byte[] {
(byte) AOUT_Request,
(byte) index,
(byte) this.AOUT[index – 1],
(byte) (this.AOUT[index – 1] >> 8)
};
do {
result = connection.bulkTransfer(endpointOUT, Packet, Packet.length, 1000);
} while ((result < 0) && (wasCloseRequested() == false));
}
}
Mai dăm un alt exemplu cu o metodă prin care se cere informația de la Microcontroler și este stocată în memoria tabletei în cadrul obiectului Device() descris mai devreme.
synchronized (this.AIN) {
for (int index = 1; index <= this.AIN.length; index++) {
/* Send the request to read the Potentiometer */
byte[] Packet = new byte[] {
(byte) AIN_Request,
(byte) index
};
do {
result = connection.bulkTransfer(endpointOUT, Packet, Packet.length, 1000);
} while ((result < 0) && (wasCloseRequested() == false));
/* Read the results of that request */
byte[] PacketResults = new byte[64];
do {
result = connection.bulkTransfer(endpointIN, PacketResults, PacketResults.length, 1000);
} while ((result < 0) && (wasCloseRequested() == false));
/* Convert the resulting data to an int */
byte[] AINBuffer = new byte[] { 0, 0, 0, 0 };
AINBuffer[0] = PacketResults[1];
AINBuffer[1] = PacketResults[2];
ByteBuffer buf = ByteBuffer.wrap(AINBuffer);
buf.order(ByteOrder.LITTLE_ENDIAN);
int AINResults = buf.getInt();
/*
* If the new results are different from the previous
* results, then send a message to the specified handler
* containing the new data.
*/
if (AINResults != this.AIN[index – 1]) {
this.AIN[index – 1] = AINResults;
handler.obtainMessage(0, new DeviceMessageAIN(index, AINResults)).sendToTarget();
}
}
}
5.3.3. Testarea parametrilor de intrare/ieșire
In această simulare se pot testa stările pinilor de intrare/ieșire cu ajutorul plăcii de testare. Folosind butoanele și potențiometrele se poate vizualiza grafic starea/valoarea lor.
Prin apăsarea butoanelor din cadrul simulării de testare sau a barelor de căutare, se poate vedea aprinderea ledurilor de pe placa de testare.
Partea software a acestei simulări este destul de simplă, se citesc valorile care sunt pe pinii de intrare și se afișează, se trimit valorile butoanelor/barelor de căutare către Microcontroler. Mai jos este o parte din codul de control al acestei simulări, o să dăm un exemplu de cum trimitem și cum preluăm un pachet de la pinii analogi, cei care au ca valoare o tensiune intre 0V si +5V.
Metoda prin care se face update în interfața la valorile AIN citind valorile care sunt stocate în obiectul Device() se poate vedea mai jos. Metoda getAIN() va returna obiectul care este dat de valoare index.
protected void updateAIN(int index, int value) {
SeekBar AIN = getAIN(index);
AIN.setProgress(value);
}
Pentru a trimite la Microcontroler valoarea pe care o stabilim prin schimbarea poziției barelor din UI, „Analog OUT” se va apela secvența de cod de mai jos.
protected void sendAOUT(int index, int value){
MainActivity.deviceObject.Send_AOUT(index, value);
}
5.3.4. Simulatorul motorului electric
In momentul în care selectăm să simulăm motorul electric, prima imagine care apare este cea de setare a parametrilor simulării. Acești parametrii se pot vedea mai jos.
După apăsarea butonului de pornire a simulării, aceste date vor fi setate și nu vor mai putea fi schimbate decât la o nouă pornire. Mai jos este codul care va face acest lucru.
final Button startButton = (Button) context.findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Spinner spinner;
String valToSet;
spinner = (Spinner)context.findViewById(R.id.initAngularDamping);
valToSet = spinner.getSelectedItem().toString();
SimulatorMotorActivity.setInitValue("initAngularDamping", Float.parseFloat(valToSet));
spinner = (Spinner)context.findViewById(R.id.stepAngularDamping);
valToSet = spinner.getSelectedItem().toString();
SimulatorMotorActivity.setInitValue("stepAngularDamping", Float.parseFloat(valToSet));
spinner = (Spinner)context.findViewById(R.id.maxAngularDamping);
valToSet = spinner.getSelectedItem().toString();
SimulatorMotorActivity.setInitValue("maxAngularDamping", Float.parseFloat(valToSet));
spinner = (Spinner)context.findViewById(R.id.stepTorque);
valToSet = spinner.getSelectedItem().toString();
SimulatorMotorActivity.setInitValue("stepTorque", Float.parseFloat(valToSet));
spinner = (Spinner)context.findViewById(R.id.maxTorque);
valToSet = spinner.getSelectedItem().toString();
SimulatorMotorActivity.setInitValue("maxTorque", Float.parseFloat(valToSet));
spinner = (Spinner)context.findViewById(R.id.motorSpeed);
valToSet = spinner.getSelectedItem().toString();
SimulatorMotorActivity.setInitValue("motorSpeed", Float.parseFloat(valToSet) / 100);
Intent simulatorView = new Intent(context, SimulatorMotorActivity.class);
context.startActivity(simulatorView);
}
});
Prin comanda context.startActivity(simulatorView) activitatea va fi pornită. În cadrul obiectului actual avem și metode generale care sunt apelate din simulator pentru a seta sau a citi valori din obiectul Device(), aceste metode vor fi apelate de către Activitatea simulatorului. Un exemplu a unei metode prin care se trimite o valoare a unui pin AOUT la Microcontroler folosind obiectul Device() inițializat în Interfața Principală.
protected void sendAOUT(int index, int value){
Device deviceObject = SimulatorMotorActivity.getDeviceInstance();
if(deviceObject != null){
deviceObject.Send_AOUT(index, value);
}
}
Simularea conține două elemente, roata motorului și roata care va fi pusă în mișcare cu ajutorul motorului. Roata motorului va fi propulsată de către variația voltajului furnizat de către automatul Siemens și acesta mișcare va lua în considerare masa, forța aplicată și mulți alți factori fizici.
Roata motorului atinge roata secundară, obținându-se un transfer de mișcare printr-o forța de frecare. Odată pusă în mișcare roata motorului, aceasta va acționa asupra celei de a doua roti, rotind-o. Aceste mișcări sunt calculate utilizând librăria Box2D care are integrată în ea un simulator de fizică foarte complex.
Un exemplu pentru crearea unui element grafic se poate vedea mai jos, acesta va crea roata motorului.
// Motor wheel
this.textureObjects.put("motorWheel", new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/motorWheel.png");
}
})
);
Acest cod se repetă pentru fiecare din elementele grafice din cadrul simulării, diferă doar numele obiectului și fișierul cu extensia png care este încărcat ca textură. Aceste Sprite-uri vor fi folosite pentru a putea avea textura obiectelor create.
Starea de repaus, când tensiunea de intrare este 0V se poate vedea în imaginea de mai jos.
Roata mică, roata mare, butoanele de + și -, butonul de închidere reprezintă sprite-uri create cu codul de mai sus. Pe lângă crearea de sprite-uri care doar aplică texturi pe obiectele propriu zise, mai avem definirea legilor fizice în cadrul simulări. Acest cod va folosi metode din librăria AndEngine.
Metoda de inițializare a roții mici a motorului:
private void initMotorWheel(){
/* Calculate the coordinates for the sprite, so its centered on the camera. */
final float centerX = (CAMERA_WIDTH – this.textureObjects.get("motorWheel").getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT-this.textureObjects.get("motorWheel").getHeight())/2;
final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1, 0, 10000);
final Sprite sprite = new Sprite(centerX – 325, centerY,
this.textureRegionObjects.get("motorWheel"), this.getVertexBufferObjectManager()) {
@Override
protected void onManagedUpdate(float pSecondsElapsed) {
super.onManagedUpdate(pSecondsElapsed);
updateMotorText(bodyObjects.get("motorWheel").getAngularVelocity());
}
};
final Body spriteBody = PhysicsFactory.createCircleBody(this.mPhysicsWorld, sprite, BodyType.DynamicBody, objectFixtureDef);
this.mScene.attachChild(sprite);
this.mScene.registerTouchArea(sprite);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, spriteBody, true, true));
final RevoluteJointDef revoluteJointDef1 = new RevoluteJointDef();
revoluteJointDef1.initialize(spriteBody, this.bodyObjects.get("ground"), spriteBody.getWorldCenter());
revoluteJointDef1.enableMotor = true;
revoluteJointDef1.motorSpeed = -1 * getInitValue("motorSpeed");
revoluteJointDef1.maxMotorTorque = 0;
this.motorJoint = this.mPhysicsWorld.createJoint(revoluteJointDef1);
this.bodyObjects.put("motorWheel", spriteBody);
this.revoluteJointDef1 = revoluteJointDef1;
}
Metoda de inițializare a roții mari pe care o învârte motorul:
private void initSpinedWheel(){
/* Calculate the coordinates for the sprite, so its centered on the camera. */
final float centerX = (CAMERA_WIDTH – this.textureObjects.get("spinedWheel").getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT – this.textureObjects.get("spinedWheel").getHeight()) / 2;
final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(0.2f, 0, 10000);
final Sprite sprite = new Sprite(centerX + 200, centerY, this.textureRegionObjects.get("spinedWheel"), this.getVertexBufferObjectManager()){
@Override
protected void onManagedUpdate(float pSecondsElapsed) {
super.onManagedUpdate(pSecondsElapsed);
updateSpinedText(bodyObjects.get("spinedWheel").getAngularVelocity());
sendSpinedData(bodyObjects.get("spinedWheel").getAngularVelocity());
}
};
final Body spriteBody = PhysicsFactory.createCircleBody(this.mPhysicsWorld, sprite, BodyType.DynamicBody, objectFixtureDef);
spriteBody.setAngularDamping(getInitValue("initAngularDamping"));
this.mScene.attachChild(sprite);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite,spriteBody true, true));
final RevoluteJointDef revoluteJointDef1 = new RevoluteJointDef();
revoluteJointDef1.initialize(spriteBody, this.bodyObjects.get("ground"), spriteBody.getWorldCenter());
revoluteJointDef1.enableMotor = false;
this.mPhysicsWorld.createJoint(revoluteJointDef1);
this.bodyObjects.put("spinedWheel", spriteBody) ;
}
Textele din stânga sus se inițializează folosind codul de mai jos, acest cod este diferit pentru fiecare text în parte, dar noi dorim să dăm doar un exemplu.
this.textObjects.put("motor", new Text(10, 10, this.mFont, "Rotatii motor: 0123456789. rpm /", new TextOptions(HorizontalAlign.LEFT), this.getVertexBufferObjectManager()));
this.updateMotorText(0);
this.mScene.attachChild(this.textObjects.get("motor"));
Avem alte două metode foarte importante, acestea fiind setMaxTorque() și sendSpinedData(). setMaxTorque() se ocupă cu imprimarea mișcării motorului în funcție de Output-ul PLC-ului, convertit în digital de către Microcontroler, codul care face acest lucru este exemplificat mai jos:
public void setMaxTorque(final float torque) {
float maxTorque = getInitValue("maxTorque");
float stepTorque = getInitValue("stepTorque");
float steps = maxTorque / stepTorque;
float stepTorqueCalculated = 0;
float torqueCalculated = torque;
if (torqueCalculated > stepTorque / 5) {
for (float i = 1; i <= steps; i++) {
stepTorqueCalculated = i * stepTorque;
if (torqueCalculated <= stepTorqueCalculated) {
torqueCalculated = stepTorqueCalculated; break;
}
}
} else {
torqueCalculated = 0;
}
if (maxMotorTorque != torqueCalculated) { maxMotorTorque = torqueCalculated; }
}
De asemenea avem metoda sendSpinedData() care în funcție de viteza cu care se rotește roata mare va trimite către microcontroler valoarea corespunzătoare. Codul se poate vedea mai jos.
private void sendSpinedData(float value){
value = -1 * value;
float maxMotorSpeed = getInitValue("motorSpeed");
float maxSpinedSpeed = maxMotorSpeed / 3.1f;
float calculatedSpinedSpeed = (value * 1023) / maxSpinedSpeed;
if(calculatedSpinedSpeed > 1023){ calculatedSpinedSpeed = 1023; }
deviceObject.Send_AOUT(1, (int)calculatedSpinedSpeed);
}
O să mai dăm un exemplu de cod prin care se face sincronizarea textelor din stânga în funcție de starea simulatorului. O să alegem să dăm doar un exemplu pentru „Puterea exercitată”
public void updateMaxTorqueText(float value){
this.textObjects.get("maxTorque").setText("Putere primita: " + String.format("%.0f", value) + " Nm / " + String.format("%.0f", getInitValue("maxTorque")) + " Nm");
}
6. Modul de funcționare al simulatorului
6.1. Testarea folosind placa de testare și modulul testare implementat pe tabletă
In modul de testare se conectează placa de testare la placa principală, utilizând cablul panglică. După aceasta se conectează Tableta la Microcontroler, folosind cablul USB. Când acest lucru este realizat atunci putem testa sistemul în doi pași.
În Tabletă va fi încărcată automat simularea Debug. Prin acționarea butoanelor și a potențiometrelor de pe placa de testare verificăm dacă datele se transmit corect și valorile corespund. În simulatorul Debug acționăm butoanele și barele pentru a verifica dacă datele sunt trimise corect către Microcontroler.
În Tabletă vom încarcă simularea motorului electric. Motorul va începe să se învârtă în funcție de tensiunea furnizată prin acționarea potențiometrului 1 și va trimite înapoi o tensiune în funcție de viteza roții mari. Această tensiune se poate vedea în intensitatea primului led de pe placa de testare.
6.2. Simulator Hard/Soft pentru motoare electrice comandate cu automate Siemens
Pregătirea hardware
Se introduce cablul panglică din placa de bază în placa de conectare cu PLC-ul, după care se introduce în Tabletă conectorul USB. Se conectează masa(GND) a plăcii de conectare la masa(GND) a PLC-ului, pinul AOUT2 la AI0 și pinul AIN1 la AQ0.
Se conectează cablul de rețea de la calculatorul pe care rulează softul TIA Portal V11 la PLC. Se deschide proiectul în softul TIA Portal, după care se apasă butonul “Go online” pentru a comunica cu PLC-ul și a primi feedback cu stările lui.
Se comută din tabloul de la laborator switch-ul AI0 pe poziția Jos și switch-ul AI1 pe poziția Sus, aceasta înseamnă că AI0 va primi curent de la mufa roșie care este conectată la Placa de conectare cu PLC-ul și AI1 va primi curent de la generatorul controlat de potențiometrul din imaginea alăturată. Potențiometrul AI1 trebuie pus în poziția 0 pentru a începe simularea din starea de repaus, setând viteza cu care dorim sa se învârtă motorul la 0.
După ce am conectat toate ansamblele putem accesa tableta, apăsam pe butonul “Motor” aflat în meniul din partea stângă. Acesta va aduce în față o fereastră în care vom configura câteva lucruri legate de cum o să se comporte simulatorul. Setările folosite se pot vedea în imaginea de mai jos:
După setarea parametrilor putem porni simularea prin apăsarea butonului “Pornește simularea”. Acest lucru va aduce pe ecranul tabletei imaginea de mai jos cu motorul în stare de repaus deoarece setarea potențiometrului este la 0, acest lucru fiind făcut anterior.
După ce simularea de pe tabletă a pornit totul trebuie sa fie funcțional, în momentul în care potențiometrul AI1 se învârte înspre +10V, în sensul acelor de ceasornic, generând o tensiune, motorul din simulator va primi un impuls în funcție de aceasta tensiune și va începe să se învârtă, punând în mișcare și roata mai mare.
Acum că tot sistemul este funcțional vom face 4 exemplificări prin care se va evidenția cum se poate ține viteza de rotire a roții mai mari, pe care motorul o pune în mișcare, prin transferul mișcării cu ajutorul forței de frecare. Vom seta o viteză de la potențiometru, după care vom aplica o frâna diferită din simulatorul de pe tabletă, vom urmării cum reacționează întreg sistemul în timp real.
In primul rând trebuie apăsat butonul din softul TIA Portal, pentru a putea primi feedback de la PLC. În momentul în care a pornit procesul de Tunning putem trece la exemple și butonul trebuie sa fie prezent. În momentul în care PLC-ul este Online și butonul start este apăsat și avem mesajul „System tunned” putem să începem să facem studiile de caz care urmează din care vom trage concluziile.
Punerea în practică 1:
Pas 1: Din starea de repaus, potențiometrul fiind setat la 0 se rotește în direcția acelor de ceasornic pentru a ajunge la 60% și frâna din simulator este setată la 0.3. În acest caz se poate vedea cum Output-ul urcă rapid la 65% și după ce Setpoint-ul este egal cu Input-ul atunci Output-ul este scăzut la 15.7% și se menține constant pentru că Setpoint-ul este egal cu Input-ul, acesta a urcat foarte rapid deoarece frâna este mica și nu avem un efort destul de mare al motorului. Aceste lucruri se pot observa pe imaginea de mai jos, imaginea din partea stânga, acesta fiind o captură din softul TIA Portal, funcționând in modul Debug.
Se poate vedea din simulare (poză dreapta) că viteza este menținută în jur de 1565 de rotații pe minut.
Pas 2: Pasul următor este să mărim frâna în simulatorul de pe tableta la 1.5, prin aceasta ne așteptăm la o urcare a liniei roșii de output, PLC-ul va creste tensiunea aplicată motorului electric pentru a compensa cu frâna exercitată și a menține viteaza constantă. Acest lucru se poate vedea în imaginile de mai jos, în care se poate observa cum linia de la Output creste de la 15.7% la 53.3% și viteza rămâne în jurul valorii de 1565 deoarece potențiometrul nu a fost mișcat de pe poziție. Acest lucru de asemenea ne confirmă că PID-ul funcționează corect și a corectat eroarea apăruta.
Punerea în practică 2:
Pas 1: Pornim de la o stare inițială în care potențiometrul este la 60% și frâna din simulator este setată la 1.5. Prin scăderea frânei la 0.3 în Tabletă se poate observa în a doua parte a graficului, din stânga, o scădere a Output-ului, acesta se întâmplă deoarece este nevoie de o tensiune mai mică pentru a menține viteza dorită, după care o scădere bruscă a Setpoit-ului (bara albastră), aceasta fiind realizată prin întoarcerea în direcția inversă a acelor de ceasornic a potențiometrului pană la valoarea de 25%, Output-ul scăzând la 10.3% și stabilizându-se.
Se poate vedea din simulare (poză dreapta) că viteza este menținută în jur de 660 de rotații pe minut.
Pas 2: Pasul următor este să mărim frâna în simulatorul de pe tableta la 1.5, prin aceasta ne așteptăm la o urcare a liniei roșii de Output, PLC-ul va crește tensiunea aplicată motorului electric pentru a compensa cu frâna exercitată și a menține viteaza constantă. Acest lucru se poate vedea în imaginile de mai jos, în care se poate observa cum linia de la output crește și viteza rămâne în jur de 660 deoarece potențiometrul nu a fost mișcat de pe poziție.
În momentul în care potențiometrul este modificat, viteza care se dorește menținută constantă scade sau crește în funcție de direcția în care este rotit, când frâna este acționată din simulatorul software din tabletă, PLC-ul va ridica tensiunea pentru a compensa și a menține viteza constantă a roții pe care motorul electric o învârte.
7. Concluzii
Sistemele de reglare automată au rolul de a asigura menținerea automată – fără intervenția omului – a unor mărimi tehnologice la o valoare prestabilită, de regim.
Folosind acest simulator putem testa cum se comportă multe echipamente în condiții extreme, spre exemplu putem testa ce se întâmplă în momentul în care frâna este foarte mare și motorul necesită o putere considerabilă pentru a funcționa, prin extinderea simulatorului cu un senzor de temperatură puteam simula o posibila explozie sau aprindere, deteriorare a parții hardware.
Cu ajutorul sistemului punem implementa un întreg ansamblu, cum ar fi spre exemplu:
funcționarea unei mașini electrice și menținerea constantă a vitezei de rulare
simularea unui lift, cu toate componentele lui
simularea umplerii unui boiler care poate avea senzori de presiune, temperatură și nivel
Se poate simula un proces tehnologic de asamblare al unei mașini sau orice altceva
se poate simula aproape orice lucru care este suportat de către librăria Box2D
Cu aceste simulări putem evalua echipamentul cu care dorim sa îl controlam, îl putem testa în condiții extreme, fără a fi nevoiți sa deterioram piese sau alte module fizice care pot avea costuri considerabile. În acest proiect de licență a fost realizat cu succes menținerea vitezei constante pentru o roată care este mișcată de către un motor electric controlat de un Automat programabil Siemens.
Se poate vedea că viteza de reacție a automatului este destul de rapidă când apare o perturbație, pe care noi am simulat-o printr-o frâna editabilă din cadrul softului implementat pe Tabletă. Iarăși motorul simulat pe tabletă reacționează la fel de repede în momentul în care potențiometrul de pe Panoul didactic este rotit setând o viteză de referință.
În acest proiect de licență sunt evidențiate bazele punerii în practică a unei simulări pentru un motor electric, dar de aici înainte se pot adaugă orice fel de simulări de la cele mai simple până la cele mai complexe, bineînțeles utilizând porturile implementate și disponibile pe microcontroler și automatul Siemens. Acestea fiind 8 porturi digitale de intrare, 8 porturi digitale de ieșire, 5 porturi de intrare care pot citi tensiuni de până la +5V și 2 porturi PWM de ieșire pe care se pot trimite o tensiune de pană la +5V.
Automatul Siemens poate fi înlocuit cu orice fel de echipament programabil și extinsă simularea pentru a putea testa orice element fizic dorim, acest lucru este exemplificat în acest proiect de licența cu ajutorul plăcii de testare.
Bibliografie
Informatică Aplicată în Industrie – Note de curs
Programare orientată pe obiecte (C++) – Note de curs
Programare în Java – Note de curs
Grafică pe calculator / Tehnici multimedia – Note de curs
http://proiectxi.wikispaces.com/Clasa+a+XII+a – fisa documentare_Regulatoare.doc
http://www.andengine.org/
http://www.microchip.com/
http://developer.android.com/
http://www.siemens.com
http://www.java.com/
http://www.cadsoftusa.com/
http://www.microchip.com/pagehandler/en-us/family/mplabx/
C manual complet – Herbert Schildt
AndEngine for Android Game Development Cookbook – Jayme Schroeder and Brian Broyles
http://www.box2d.org/manual.html
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Simulator HardSoft pentru motoare electrice [307668] (ID: 307668)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
