Brat Robotic, Comandat Electronic
Cuprins
Introducere…………………………………………………………………………………………..11
Capitolul I Exoscheletul……………………………………………………………………..13
Istoric………………………………………………………………………………..13
Necesitatea unui exoschelet…………………………………………………………13
Produse curente……………………………………………………………………..14
Platforma HULC……………………………………………………………………14
Produse in curs de dezvoltare……………………………………………………….16
Capitolul II Limitări…………………………………………………………………………17
Sursă de alimentare…………………………………………………………………17
Schelet………………………………………………………………………………17
Actuator……………………………………………………………………………..18
Flexibilitatea încheieturilor…………………………………………………………18
Capitolul III Motoare Pas cu Pas……………………………………………………………19
Principiul de funcționare……………………………………………………………19
Tipuri de motoare……………………………………………………………………20
Circuite de control…………………………………………………………………..21
Tipuri de control…………………………………………………………………….22
Aplicații……………………………………………………………………………..24
Capitolul IV Microcontrolerul………………………………………………………………25
Istoric………………………………………………………………………………..25
AVR Atmel………………………………………………………………………….26
Interfețe de programare……………………………………………………………..28
Capitolul V Controlerul ULN2003A………………………………………………………..31
Tranzistor Darlington……………………………………………………………….31
Specificații…………………………………………………………………………..31
Aplicații……………………………………………………………………………..31
Capitolul VI Brațul………………………………………………………………………….33
Scheletul…………………………………………………………………………….33
Schema electrică…………………………………………………………………….34
Interfațarea microcontroler-PC………………………………………………………37
Interfațarea microcontroler-motor…………………………………………………..39
Alegerea motoarelor și montarea acestora………………………………………….40
Consola de control direct……………………………………………………………43
Sisteme de siguranță…………………………………………………………………43
Capitolul VII Programarea microcontrolerului……………………………………………..45
Programarea utilizând bootloader-ul………………………………………………..45
Explicarea codului…………………………………………………………………..46
Capitolul VIII Rezultatele testelor………………………………………………………….55
Bibliografie …………………………………………………..…………………………….59
Anexe……………………………………………………………………………………….61
Lista Figurilor
Figura 1.1: Exoscheletul HULC pe un soldat american……………………………………………..15
Figura 3.1: Motor pas cu pas…………………………….……………………………….…………19
Figura 3.2: Bobinajul pentru un motor pas cu pas unipolar……………………….……………..…20
Figura 3.3: Motor pas cu pas conectat la circuitul de control Adafruit Motor Shield ce se utilizează cu ArduinoI……………..……………………………………………………………………….…..21
Figura 3.4: Diferite forme de undă utilizate pentru controlul motoarelor…………………….…….23
Figura 4.1: Microcontrolere AVR ATmega…………………………………………….…………..25
Figura 4.2: ATmega8, cip cu 28 de pini…………………………………….……………………….27
Figura 5.1: Schema internă a cipului ULN2003A…………………………………………………..33
Figura 6.1: Test de mobilitate a unui deget format din 3 piese mobile……………………………..33
Figura 6.2: Schema de plecare desenată în EAGLE………………………………………………..34
Figura 6.3: Schema finală a proiectului, fără legăturile la motoare, executată în EAGLE…………35
Figura 6.4: Schema PCB obținută din programul EAGLE, utilizându-se funcția de auto-rutare…..36
Figura 6.5: Convertorul de nivel MAX232…………………………………………………………37
Figura 6.6: Forme de undă la intrarea (TTL) și ieșirea convertorului MAX232/MAX202…………37
Figura 6.7: Plăcuța ce conține controlerul de motor ULN2003A…………………………………..39
Figura 6.8: Legătura directă plăcuță de control, motor……………………………………………..40
Figura 6.9: Motorul MingJong ST28……………………………………………………………….41
Figura 6.10a: Ansamblul de transmisie observat pe două degete…………………………………..42
Figura 6.10b: Ansamblul de transmisie observat pe toate cele trei degete…………………………42
Figura 6.11: Poză din interior a sistemului de montare a motoarelor………………………………42
Figura 6.12: Placa de test cu toate legăturile necesare montate…………………………………….43
Figura 8.1: Brațul mecanic cu pumnul complet închis……………………………………………..55
Figura 8.2:Brațul mecanic cu pumnul complet deschis…………………………………………….56
Figura 8.3: Brațul mecanic ținând în mână o sticla de plastic cu 1L de apă în ea………………….57
Figura 8.4: Brațul cu degetele în poziție închisă pentru testul de prins cu două degete……………58
Lista tabelelor
Tabel 6.1: Tabelul de conectare al pinilor la mufa DB9 mamă…………………………………….38
Lista Acronimelor
ADC: Analog to Digial Converter: Convertor analog-digital;
AVR: Alf and Vegard’s RISC processor: procesorul RISC al lui Alf si Vegard;
DCE: Data Communication Equipment: Echipament de comunicații de date;
DTE: Data Terminal Equipment: Echipament terminal de date;
EEPROM: Electronicaly Erasable Programmable Read-Only Memory: Memorie programabilă ce se poate șterge electronic;
EPROM: Erasable Programmable Read-Only Memory: Memorie programabilă ce se poate șterge;
HULC: Human Universal Load Carrier; Caraus Universal Uman;
ISP: In System Programming: programare în dispozitiv;
LCD: Liquid Crystal Display: Ecran cu cristale lichide;
LS12: LIFESUIT TWELVE;
LS6: LIFESUIT SIX;
LSI: LIFESUIT ONE;
NOR: NOR se referă la tipul porților utilizate in construcția memoriei;
OTP ROM: One Time Programmable Read-Only Memory: Memorie ce se poate programa o singură dată;
OTP: One Time Programmable: programabil o singură dată;
PC: Personal Computer; Calculator personal;
PCB: Printed Circuit Board: circuit imprimat pe placă;
PROM: Programmable Read-Only Memory: Memorie programabilă;
PWM: Pulse Width Modulation: Modularea lățimii impulsului;
RAM: Random Access Memory: Memorie cu acces aleator;
RISC: Reduced Instruction Set Computer: Calculator cu set redus de instrucțiuni;
SPI: Serial Peripheral Interface: interfață periferică serială;
SRAM: Static Random Access Memory: Memorie statică cu acces aleator;
TTL:Transistor-Transistor Logic: Logică Tranzistor-Tranzistor;
USB: Universal Serial Bus: Magistrală serială universală;
Introducere
Scopul acestei lucrări este realizarea unui exoschelet ce are ca funcționalitate, un set de mișcări similar cu cele ale brațului uman. Obiectivele propuse pentru acest proiect au fost construirea unui șasiu metalic, dezvoltarea unui software de control direct al brațului, construirea unei console interne de control direct, crearea unor teste bazate pe prinderea unor obiecte de dimensiuni si greutăți variate pentru a demonstra funcționalitatea brațului. Pentru executarea obiectivelor, s-a plecat de la o platformă metalica construita în întregime prin metode și materiale proprii, pentru partea electronică utilizându-se resursele din laboratorul B210.
Motivul alegerii acestui proiect a fost crearea unui sistem cu scopul utilizării în misiuni de căutare și salvare (Search and Rescue). Brațul face parte dintr-un sistem complex, ce acoperă tot corpul utilizatorului, având rolul de amplificare a forței cât și protecția pilotului. Sistemul poate fi utilizat în cazuri de urgențe (cutremure, incendii) de către echipajele de salvare pentru mișcarea dărâmăturilor și intrarea în incinta clădirilor dezafectate pentru a putea oferii ajutor posibilelor victime. Avantajul oferit de un astfel de sistem este mobilitatea sporită, cât și abilitatea de a executa manevrele de salvare într-un timp scurt, astfel mărind șansele de supraviețuire ale victimelor și salvatorilor.
Brațul prezentat este doar prototipul de plecare pentru acest sistem denumit „Kuro Usagi” ce în limba japoneză înseamnă „Iepurele Negru”.
Pentru construirea acestui braț au fost folosite motoare pas-cu-pas, un șasiu metalic al cărui design a fost inspirat din protezele de top. Mișcarea degetelor a fost simplificata utilizând pârghii metalice, construite cu aceleași materiale ca brațul. Pentru sistemul de transmisie s-a folosit un mecanism de tipul roată dințată-melc.
Controlul motoarelor s-a făcut în două moduri: Un modul automat și un modul de control direct via o consola internă. „Creierul” brațului este un microcontroler de tip ATmega 16. Consola internă de control direct este alcătuita dintr-o platformă pe care sunt montate butoane responsabile pentru fiecare deget individual.
Sistemul „Kuro Usagi” este gândit pentru a putea fi atașat pe platforma americană deja existentă HULC. Astfel greutatea sistemului nu ar fi simțită de către utilizator, păstrând mobilitatea sporită pentru care a fost creat. Sistemul curent este implementat utilizând motoare electrice, dar pentru îmbunătățiri ale forței exercitate se pot utiliza pompe hidraulice de dimensiuni mici, acestea având o putere mult mai mare. De asemenea șasiul poate fi schimbat pentru a conferi o rezistență mai mare și masă redusă, utilizând în loc de metal fibră de carbon.
Microcontrolerul a fost programat utilizând o legătură directă între PC și microcontroler (comunicație serială).
Legătura microcontroler-motor a fost făcută utilizând controlerul ULN2003A, controler prefabricat.
Capitolul I – Exoscheletul
Istoric
Primul dispozitiv similar unui exoschelet a fost un set de aparate pentru asistatul mersului, alergatului si săritului dezvoltat in anul 1890 de către rusul Nicholas Yagn. Dispozitivul utiliza saci cu aer comprimat pentru stocarea energiei, care asistau mișcările utilizatorului. Din nefericire acest dispozitiv necesita o forță externă, umană pentru o bună funcționare. În 1917 inventatorul american Leslie C. Kelley a dezvoltat un dispozitiv pe care l-a numit pedomotor, un dispozitiv ce utiliza abur și ligamente artificiale ce acționau în paralel cu mișcările utilizatorului. În cazul acestui dispozitiv energia era generată separat de utilizator.
Primul exoschelet în adevăratul sens al cuvântului a fost dezvoltat în anii 60’ de către General Electric în scopuri militare. Costumul numit „Hardiman” făcea ridicarea a 110 kilograme să se simtă ca si cum ar fi 4,5 kilograme. Costumul utiliza pompe hidraulice împreună cu circuite electrice amplificând forța utilizatorului cu un factor de 25. Un sistem numit force-feedback a fost dezvoltat astfel încât utilizatorul să simtă forța exercitată de obiectele pe care acesta le manipula.
Deși ideea originală a fost promițătoare, costumul „Hardiman” avea limitări masive, în principal datorate greutății costumului, aceasta fiind de 680 de kilograme. Un alt impediment era că acest sistem se baza pe o uniune tip stăpân-sclav, în care utilizatorul era componenta stăpân iar costumul era componenta sclav. Acest sistem avea timpi de răspuns insuficient de rapid pentru o unitate om-mașină eficientă. De asemenea la utilizarea completa a sistemului, acesta avea reacții violente, astfel fiind nefăcându-se niciodată teste cu un pilot uman în interiorul costumului.
Laboratoarele Los Alamos au lucrat la un proiect de exoschelet tot în anii 60’ numit „Project Pitman”. În 1986, un prototip de exoschelet numit LIFESUIT (costumul vieții) a fost creat de către Monty Reed, un soldat american ce și-a rupt coloana într-un accident de parașutism. În anul 2001 a fost construit LSI (prima iterație a cestui costum), în 2003 a fost construit LS6 iar în 2005 LS12. Monty Reed împreună cu costumul LIFESUIT XII a setat recordul de viteză pentru mersul într-un costum robotic, parcurgând 3 mile in 90 de minute. Versiunea curentă LIFESUIT 14 poate parcurge o milă pe baterie și poate ridica o greutate de 92 de kilograme pentru utilizator.
Necesitatea unui exoschelet
Una din utilizările principale ale unui exoschelet este în domeniul militar, acela de a ajuta un soldat să care greutăți mari (80-300 de kilograme) în timp ce aleargă sau urcă pe trepte. Nu doar că ar putea căra greutăți mai mari, dar ar putea de asemenea utiliza armament și armură mai grea.
O altă arie de utilizare ar putea fi în domeniul medical, în special în zona de asistență medicală. Datorita problemelor inevitabile cum ar fi scăderea personalului medical și creșterea numărului de persoane învârstă ce au nevoie de îngrijire medicală, o echipa din Japonia se axează pe crearea unui exoschelet al cărui scop este ajutarea asistenților medicali pentru a ridica și căra pacienții.
Exoscheletele ar putea fi utilizate și în zona recuperărilor fizice pentru pacienții ce au suferit infarcturi sau accidentări ale coloanei vertebrale. Un exoschelet ar putea reduce personalul necesar, exoscheletul permițând unui singur terapeut să se poată ocupa de orice pacient, oricât de extensive ar fi rănile acestuia, acum fiind necesari mai mulți terapeuți pentru un singur pacient. De asemenea recuperarea fizică ar putea fi mai uniformă, analiza rezultatelor mai ușor de făcut și fiecare exoschelet ar putea fi personalizat pentru fiecare pacient în parte.
Exoscheletele ar putea fi văzute ca roboți purtabili. Un robot purtabil este un sistem mecatronic care este conceput în jurul formei și funcționării corpului uman. Centru de Cercetare German pentru Inteligență Artificială a dezvoltat două exoschelete de uz general, CAPIO si VI-bot. Operarea de la distanță și amplificarea puterii au fost primele aplicații, dar după descoperiri recente domeniul de aplicabilitate s-a mărit.
Produse curente
ReWalk: este un sistem ce poseda articulații motorizate ale soldurilor și genunchilor, pentru a ajuta persoanele cu dizabilități ale membrelor inferioare, cum ar fi cele datorate de răni ale coloanei vertebrale, să se ridice singure, să meargă și să urce trepte.
Sarcos/Raytheon XOS exoschelet pentru brațe și picioare, utilizat în proiecte militare, cântărește 48 de kilograme permițând utilizatorului să ridice o greutate 90 de kilograme cu foarte puțin efort. În 2010 a fost dezvăluit sistemul XOS 2 care oferă o mobilitate îmbunătățită, putere mai mare și consum redus.
HULC al companiei ESKO Bionics: sistem pentru picioare, principalul rival al sistemului XOS. Cântărește 24 de kilograme și ii permite utilizatorului să ridice o greutate de 91 de kilograme pe un suport dorsal atașat exoscheletului, independent de utilizator. O versiune modificată a HULC-ului este în dezvoltare cu scopul de a ajuta pacienții să meargă.
eLegs al companiei ESKO Bionics: un sistem hidraulic utilizat de persoane cu dizabilități grave ale membrelor inferioare să meargă, cu ajutorul cârjelor.
HAL 5 al companiei Cyberdine, sistem pentru brațe și picioare. Primul cyborg purtabil ce îi permite utilizatorului să ridice greutăți de 10 ori mai mari față de ce ar putea în mod normal. HAL 5 este folosit în spitalele din Japonia și a primit certificare globala de siguranță în 2013.
Honda Exoskeleton Legs: Cântărește 6,5 kilograme și este dotat cu un scaun pentru utilizator.
Platforma HULC
HULC-ul este o platformă inferioară (este montată pe membrele inferioare), de uz general, utilizată pentru a căra greutăți mari. Această platformă este un exoschelet antropomorf, ce utilizează un sistem hidraulic pentru a se putea mișca. Scopul acestui exoschelet este de a permite soldaților implicați în zone de conflict să poată căra greutăți de până la 90 de kilograme, mergând cu o viteză constantă de 16 km/h. Dezvoltarea acestui exoschelet a început în anul 2000 la laboratorul de robotică și inginerie umană din Berkley și sistemul a fost anunțat public în anul 2009, cu drepturi complete de licențiere fiindu-i acordate lui Lockheed Martin.
Figura 1.1: Exoscheletul HULC pe un soldat american (referința 1)
În iulie 2010 Lockheed Martin a câștigat un contract în valoarea de 1,1 milioane de dolari pentru testarea și dezvoltarea unităților HULC. Testele de laborator au fost programate pentru anul 2011 urmate de teste pe teren.
În mai 2012 Lockheed a anunțat un sistem HULC îmbunătățit, o versiune mai ușoară și cu consum de energie redus, ce poate funcționa în pas de marș timp de 8 ore, sau poate aștepta în modul „stand-by” pentru câteva zile. Acest sistem urma a fi testat în luna septembrie a aceluiași an. Deși sistemul a fost testat cu succes, nu a fost acceptat de către armata americană.
HULC a fost dezvoltat pentru a fi ușor de montat. Soldatul trebuie doar să se așeze pe platformele ce se află sub tălpi, după care, cu ajutorul unor benzi late, din material textil ce vor fi înfășurate în jurul coapselor, șoldurilor și umerilor, soldatul va fi fixat în exoschelet. Senzori din platformele de sub tălpi transmit semnale unui microcalculator aflat în interiorul exoscheletului ce controlează sistemul hidraulic pentru a amplifica și ușura mișcările utilizatorului. Flexibilitatea sistemului le permite soldaților să alerge, să meargă, să îngenuncheze și să execute o gamă variată de mișcări necesare într-o situație de luptă.
Nu există un sistem dedicat de control, ci prin utilizarea senzorilor, exoscheletul este comandat să se miște în paralel cu mișcările soldatului. Șasiul de titan al exoscheletului împreună cu sistemul hidraulic amplifică performanțele soldatului ce poartă acest exoschelet. De asemenea modularitatea acestui exoschelet permite interschimbarea componentelor foarte ușor.
In curs de dezvoltare
MINDWALKER dezvoltat de Comisia Europeană: este un exoschelet controlat prin unde cerebrale, pentru persoane paralizate.
Altacro dezvoltat de Universitatea Vrije din Bruxelles: este un exoschelet pentru persoane cu dizabilități.
ExoAtlet Med: este un exoschelet pentru persoane cu dizabilități locomotorii.
Proiectul armatei americane, Future Soldier 2030 (soldatul viitorului 2030).
Capitolul II. Limitări
Inginerii ce se ocupă de dezvoltarea exoscheletelor se confruntă cu provocări tehnologice masive pentru a putea construi un costum capabil de mișcări, dar este în continuare sigur de utilizat, fără o perioadă lungă de instruire.
Sursă de alimentare
Una din cele mai mari probleme este sursa de alimentare. Astăzi există puține surse de alimentare cu o densitate de energie destul de mare pentru a putea susține un exoschelet complet pentru mai mult de câteva ore.
Celulele primare non-reîncărcabile tind să posede o densitate de energie mai mare și să o păstreze pe o durată mai mare de timp, dar este necesar transportul celulelor de schimb când cele primare au fost consumate. Celulele reîncărcabile pot fi reutilizare dar ar putea necesita transportul unei stații de încărcare, care să încarce rapid celulele, ori să permită schimbarea celulelor cu altele ce se încărcau lent.
Motoarele cu combustie internă oferă o cantitate mare de energie, dar funcționează constant având un consum mediu doar pentru menținerea în funcțiune a motorului. Dezavantajul este că atunci când nu este utilizat în mod activ tot consumă combustibil. Motoarele de dimensiuni și greutate redusă trebuie să funcționeze la viteze mari pentru a putea extrage suficientă energie dintr-un volum cilindric mic, ceea ce duce la dificultăți în menținerea unui nivel redus de zgomot și induce vibrații în restul sistemului. De asemenea motoarele cu combustie internă produc o căldură foarte mare, apărând necesitatea utilizării unui sistem de răcire mai bun sau ecranare termică, care vor mări greutatea sistemului.
Surse de alimentare pe bază de baterii sunt o posibilitate, deoarece sunt bune în a oferi putere instantanee și modulată; energia chimică stocată fiind păstrată când nu sunt conectate în sarcină.
Celule de energie electrochimice cum ar fi celulele cu oxid solid, sunt de asemenea considerate ca surse de alimentare pentru exoschelete, deoarece produc energie instantanee similar bateriilor și pot conserva energie când nu sunt utilizate. De asemenea pot fi reîncărcate rapid utilizând combustibili lichizi cum ar fi metanolul. Din nefericire necesita temperaturi mari pentru a funcționa optim, temperatura de 600°C fiind considerată scăzută pentru aceste celule.
Scheletul
Experimentele inițiale implicând exoschelete sunt desfășurate materiale ieftine și ușor de modelat cum ar fi oțel sau aluminiu. Dar oțelul este mult mai greu, iar cu cât costumul trebuie să lucreze pentru a-și depăși propria greutate, va scădea eficiența sistemului. Aliajul de aluminiu este ușor, dar poate ceda la greutate excesivă; este inacceptabil pentru un exoschelet să cedeze în condiții de stres mecanic mare, rezultând în accidentarea utilizatorului. Pe măsură ce etapele dezvoltării depășesc fazele preliminare inginerii pot progresa către materiale mai scumpe, mai durabile și la fel de ușoare, cum ar fi titan-ul, și să utilizeze metode de construcție a pieselor mai complexe, spre exemplu plierea plăcilor de carbon.
Actuatoare
Necesitatea unor modele puternice și ușoare este valabilă și pentru actuatoarele încheieturilor. Pistoanele hidraulice standard sunt puternice si precise dar au dezavantajul greutății și lichidul hidraulic se poate scurge pe utilizator. Pistoanele pneumatice sunt în general mult prea imprecise pentru mișcări fine deoarece pistoanele pneumatice au tendința de a „sări” iar lungimea mișcării va varia în funcție de cantitatea de gaz presurizat.
Servomotoarele electrice sunt in general mai eficiente, utilizând magneți permanenți și cutii de transmisie pentru a obține cuplu mare și responsivitate mare păstrând dimensiunile mici. Servomotoarele cu roți dințate pot utiliza și sisteme electronice de frânare pentru a menține o poziție fixă consumând puțină energie. Adițional, noua serie de actuatoare elastice și alte actuatoare deformabile sunt propuse pentru utilizare în exoschelete robotice pentru a simula rigiditatea membrelor umane.
Flexibilitatea încheieturilor
Flexibilitatea anatomiei umane este un alt aspect important în dezvoltare. Multiple încheieturi umane cum ar fi șoldurile și umerii funcționează pe principiul bilă-soclu cu centrul de rotație în interiorul corpului. Este dificil pentru un exoschelet să copieze exact mișcările acestui sistem bilă-soclu utilizând un sistem de puncte externe de pivotare pe o singură axă, limitând flexibilitatea utilizatorului.
Se poate utiliza un sistem bilă-soclu extern, separat pentru șolduri și umeri, dar asta ar duce la apariția unor țevi paralele cu oasele utilizatorului. Odată cu rotirea exoscheletului lungimea dintre încheieturile genunchiului și cotului se vor mări si micșora ducând la nealinierea încheieturilor mecanice cu cele ale utilizatorului. Acest decalaj între utilizator si exoschelet poate fi permis, sau costumul poate fi construit sa se lungească sau scurteze asistat pe parcurs ce se mișcă utilizatorul pentru a păstra genunchii și coatele aliniate.
O soluție parțială pentru mișcări mai fluide pe cele trei axe este utilizarea unei bile sferice goală pe dinăuntru ce acoperă articulația, cu articulația umană ca centru de rotație. Rotația in jurul acestei bile poate fi limitată daca nu se utilizează un sistem glisant care să se extindă sau contracte pe măsură ce încheietura parcurge gama întreagă de mișcări.
Capitolul III – Motoare Pas cu Pas
Pentru proiectul curent în loc să fie utilizate servomotoare au fost utilizate motoare pas cu pas pentru un control mai bun al mișcărilor și cuplu mai mare.
Un motor pas cu pas este un motor electric de curent continuu fără perii ce își divide rotația într-un număr de pași egali. Poziția motorului poate fi comandată și menținută la unul din acești pași fără a fi necesară utilizarea unui senzor de răspuns, atâta timp cât motorul este dimensionat corespunzător aplicației.
Figura 3.1: Motor pas cu pas (referința 2)
Principiul de funcționare
Motoarele de curent continuu cu perii se rotesc constant când este aplicată o tensiune continuă la terminale. Motorul pas cu pas este cunoscut pentru abilitatea sa importantă de a converti un tren de impulsuri la intrare în incrementări precise ale poziției axului. Fiecare impuls mișcă axul un unghi fix. Motoarele pas cu pas au electromagneți cu „dinți” aranjate in jurul axului central ce are forma de roată dințată. Electromagneții sunt activați de un circuit extern de control, cu ar fi un microcontroler. Pentru a face axul să se rotească, prima dată este activat un electromagnet, ce va atrage dinții roții. Când dintele este aliniat cu primul electromagnet, ceilalți vor fi decalați față de următorul electromagnet. Asta înseamnă că atunci când următorul electromagnet este activ iar cel curent este oprit axul se va roti pentru a alinia dintele cu electromagnetul. De aici procesul este repetat. Fiecare mișcare de „rotație” este numită pas, cu un număr întreg de pași formând o rotație completă. Astfel axul motorului poate fi rotit cu un unghi foarte precis.
Tipuri de motoare
Există patru tipuri de motoare pas cu pas:
Motoare pas cu pas cu magneți permanenți (pot fi împărțite în „tin-can”(„cutii de tablă”) și „hibride”, cutiile de tablă fiind produsele mai ieftine și hibridele produse cu rulmenți de calitate mai mare, unghi de incrementare mai mic și densitate de putere mai mare);
Motoare pas cu pas sincrone hibride;
Motoare pas cu pas cu repulsie variabilă;
Motoarele pas cu pas cu magneți permanenți utilizează magneți permanenți în rotor și funcționează pe atracția și repulsia dintre magneții rotorului și electromagneții statorului. Motoarele pas cu pas cu repulsie variabilă au un rotor simplu din fier, și funcționează pe principiul ca repulsia minimă apare odată cu distanța minimă, punctele rotorului fiind atrase de către polii magnetici ai statorului.
Motoare pas cu pas cu două faze
Există două tipuri de aranjamente ale bobinajului pentru bobinele electromagnetice într-un motor cu două faze: bipolar și unipolar.
Motorul pas cu pas unipolar are o singură înfășurare pe axul central pe fază. Fiecare secțiune de înfășurare este activată pentru fiecare direcție a câmpului magnetic. Deoarece în acest aranjament un pol magnetic poate fi inversat fără a schimba direcția curentului, se poate utiliza un circuit de comutare foarte simplu (de exemplu un singur tranzistor) pentru fiecare bobinaj. În mod uzual înfășurarea centrală a fiecărui bobinaj este făcut comun, rezultând în trei fire pentru fiecare fază și șase fire pentru un motor uzual cu doua faze. Uzual cele două fire de fază comune sunt conectate intern, rezultând in cinci fire.
Un microcontroler sau un controler de motor pas cu pas poate fi utilizat pentru a activa tranzițiile în ordine corespunzătoare, iar această facilitate în utilizare face motoarele pas cu pas foarte populare pentru începători, fiind probabil cea mai ieftină metodă de a obține mișcare unghiulară precisă.
Figura 3.2 : bobinajul pentru un motor pas cu pas unipolar. (referința 3)
Motorul pas cu pas bipolar are o singură înfășurare pe fază. Curentul trebuie inversat prin înfășurare pentru a inversa polul magnetic, rezultând în circuite de comandă mai complicate, uzual utilizându-se o punte H. Sunt prezente două fire pe fiecare fază. Efectul frecării statice au fost observate în cazul utilizării anumitor topologii ce utilizează puntea H.
Deoarece înfășurările sunt utilizate mai bine, motoarele pas cu pas bipolare sunt mai puternice decât cele unipolare pentru aceeași greutate. Asta este datorat spațiului fizic ocupat de înfășurări. Un motor pas cu pas unipolar are de două ori mai multe fire în același spațiu fizic, dar doar jumătate sunt utilizate simultan, rezultând într-o eficiență de 50% (sau 70% din cuplul maxim disponibil). Motorul pas cu pas bipolar este mai complicat de controlat, dar deoarece exista o abundență de circuite pre-fabricate pentru acest rol, controlul devine o sarcină relativ ușoară.
Un motor pas cu pas cu opt fire poate fi legat să acționeze ca un motor unipolar, dar firele comune nu sunt legate intern. Acest tip de motor poate fi legat în diferite configurații:
Configurație unipolară;
Configurație bipolară cu înfășurările înseriate. Acesta oferă inductanță mai mare, dar curent mai mic pe înfășurări;
Configurație bipolară cu înfășurările paralele. Aceasta necesită un curent mai mare, dar poate avea performanțe îmbunătățite deoarece înfășurările au inductanță redusă;
Configurație bipolară cu o singură înfășurare pe fază. În această configurație motorul va rula doar pe jumătate din înfășurările disponibile, ceea ce va rezulta în cuplu mai mic dar și un curent necesar mai mic.
Circuite de control
Performanțele unui motor pas cu pas sunt puternic dependente de circuitul de control. Cuplul poate fi mărit la viteze mai mari de rotație dacă polii statorului ar putea fi inversați mai rapid, factorul limitator fiind inductanța înfășurărilor. Pentru a depăși efectul inductanței, trebuie crescută tensiunea de alimentare. Acesta duce la necesitatea limitării curentului ce ar putea fi indus de această creștere a tensiunii.
Diferite tipuri de circuite de control utilizate:
Circuite de control L/R;
Circuite de control cu „tăietor”;
Circuitele de control L/R sunt cunoscute ca fiind controlere cu tensiune constantă, deoarece o tensiune constantă pozitivă sau negativă este aplicată pe fiecare înfășurare pentru a seta pozițiile pasului. Din nefericire, curentul, nu tensiunea generează cuplul la axul motorului. Curentul I prin fiecare înfășurare este legat de tensiunea aplicată V prin inductanța înfășurării L și rezistența înfășurării R. Rezistența R determină curentul maxim prin înfășurare conform legii lui Ohm: I=V/R. Inductanța L determină rata maximă de schimbare a curentului prin înfășurare conform legii inductoarelor: dI/dt=V/L. Astfel când este utilizat un circuit de control L/R, viteza maximă a motorului este limitată de inductanță deoarece la o anumită valoare a vitezei tensiunea U se va schimba mai rapid decât se poate schimba curentul I. Simplificat rata de schimbare este L/R (de exemplu pentru o inductanță de 10mH cu aproximativ 2 ohmi rezistență va dura 5ms pentru a ajunge la doua treimi din cuplul maxim și 24ms pentru a ajunge la 99% din cuplul maxim). Pentru a obține cuplu mare la viteze mari este necesară o tensiune mare de alimentare, o inductanță și o rezistență scăzută. Cu un circuit de control L/R se poate mări tensiunea de alimentare peste cea nominală a motorului adăugând pe fiecare fir câte o rezistență în serie. Acest lucru va cauza pierderi de putere, și încălzirea circuitului, drept urmare este considerată ca fiind o soluție slabă, chiar daca este una ieftină și ușoară.
Circuitele de control cu „tăietor” sunt cunoscute ca fiind controlere de curent constant, deoarece generează în fiecare înfășurare un curent constant în loc sa aplice o tensiune constantă. La fiecare pas nou, este aplicată o tensiune inițială foarte mare. Aceasta cauzează curentul sa crească foarte rapid deoarece dI/dt=V/L, unde V este foarte mare. Curentul în fiecare înfășurare este monitorizat de către controler, în general prin măsurarea tensiunii pe o rezistență foarte mică în serie cu fiecare înfășurare. Când curentul trece peste o anumită limită superioară impusă, tensiunea de alimentare este oprită, sau „tăiată”, în mod uzual utilizându-se un tranzistor de putere. Când curentul scade sub un anumit prag inferior tensiunea este pornită din nou. Astfel curentul este menținut relativ constant pentru fiecare pas. Sunt necesare circuite în plus pentru măsurarea curentului pe fiecare înfășurare și pentru a controla comutările tensiunii, dar oferă posibilitatea generării unui cuplu mare la viteze mai mari decât în cazul circuitelor de control L/R. Circuitele integrate sunt cele mai utilizate în acest scop.
Tipuri de control
Motorul pas cu pas este un motor de curent alternativ sincron polifazat și este controlat în mod ideal printr-un curent sinusoidal. O formă de undă a unui pas complet este o aproximare grosolană a unei sinusoide, și este motivul pentru care motorul prezintă vibrații. Diverse tehnici de control au fost dezvoltate pentru a aproxima o formă de undă de control sinusoidală: acestea sunt tehnicile „jumătate de pas” și „micro-pasul”.
Metoda formă de undă (o singură fază este activă).
În această metodă doar o singură fază este activa la orice moment de timp. Are același număr de pași ca metoda de control cu pas întreg, dar motorul va avea mult mai puțin cuplu. Este rar folosit. În figura de mai sus rotorul are 25 de dinți și este nevoie de 4 pași pentru a roti un dinte cu o poziție. Astfel vom avea 25*4=100 de pași necesari pentru o rotație completă, iar fiecare pas va avea 360/100=3,6 grade.
Metoda pas întreg (două faze sunt active).
Aceasta este metoda utilizată uzual pentru a controla un motor pas cu pas. Două faze sunt active simultan rezultând într-un cuplu maxim. În momentul în care o fază este activată, o altă fază este de-activată. Metoda formă de undă și metoda pasului întreg sunt aproape identice având același număr de pași, dar au cupluri complet diferite.
Metoda jumătate de pas
Această metodă alternează între două faze pornite și o singură fază pornită. Această metodă mărește rezoluția unghiulară. De asemenea motorul are cuplu mai mic (aproximativ 70% din cuplul obținut prin metoda pasului întreg). Acest neajuns poate fi compensat prin mărirea curentului prin înfășurarea activă. Avantajul acestei metode de control este aceea că nu este necesară modificarea circuitului de control pentru a fi suportată. În figura 4 dacă modificăm metoda la jumătate de pas, vor fi necesari 8 pași pentru ca un dinte să se miște cu o poziție. Astfel vom aveam 25*8=200 de pași pentru o rotație completă și fiecare pas va avea 360/200=1,8 grade. Unghiul per pas este jumătate din cel de la metoda pasului întreg.
Micro-pasul
Aceasta metodă mai este cunoscută sub numele de pas sinusoidal/cosinusoidal, în care curentul este aproximat cu o formă de undă alternativă. Această metodă este cea mai comună, dar pot fi utilizate și celelalte metode.
Indiferent de metodele folosite cu cât pașii devin mai mici cu atât funcționarea motorului devine mai lină, astfel micșorând rezonanța motorului și orice altă componentă de care motorul ar putea fi conectat. Rezoluția va fi limitată de sursele de erori dintre motor și dispozitivul final. Reductoare pot fi utilizate pentru a mări rezoluția.
Repetabilitatea pasului este o calitate importantă a motoarelor pas cu pas și în același timp motivul fundamental pentru utilizarea acestora.
Aplicații
Motoarele pas cu pas controlate de calculator sunt un sistem utilizat de poziționare. Sunt utilizate în mare parte în aplicații ce necesită plasare de piese. În domeniul laserelor și opticii sunt adesea utilizate pentru echipamente de poziționare foarte precise. Alte utilizări sunt în domeniul liniilor de împachetare, sau poziționarea valvelor pentru sisteme de control al fluidelor.
Comercial motoarele pas cu pas sunt utilizate în sisteme de dischete floppy, în sisteme de scanare plate, imprimante, sisteme de scanare, unități optice pentru discuri, iluminare inteligentă, lentile de camere, mașinării cu control numeric computerizat și recent în imprimante 3D.
Capitolul IV – Microcontrolerul
Un microcontroler (abreviat ca μC, UC sau MCU) este un calculator, integrat pe un singur cip, ce conține un procesor, o memorie și o serie de periferice programabile de intrare/ieșire. Memoriile sunt de tipul RAM feroelectric, NOR flash sau OTP ROM mai pot fi incluse pe cip împreună cu mici cantități de memorie RAM. Microcontrolerele sunt create pentru utilizarea în aplicații integrate, spre deosebire de microprocesoarele utilizate în calculatoare sau alte aplicații de uz general.
Microcontrolerele sunt utilizate în aplicații si dispozitive automate, cum ar fi sisteme de control al motoarelor automobilelor, dispozitive medicale implantabile, telecomenzi, mașinării de birou, electrocasnice, unelte electrice, jucării și alte sisteme integrate. Reducând dimensiunea și costul, comparat cu un sistem ce utilizează un microprocesor, memorie și dispozitive de intrare/ieșire, microcontrolerele fac controlul digital al dispozitivelor să fie mult mai economic. Microcontrolere de semnale combinate (analogice si digitale) sunt foarte comune, integrând componente analogice necesare controlului sistemelor non-digitale. Unele microcontrolere pot utiliza cuvinte pe patru biți și pot funcționa la frecvențe joase de până la 4 kHz, pentru consum redus de putere (sub 10 mW sau chiar μW). În general au abilitatea de a-și menține funcționalitatea în timp ce așteaptă un eveniment, spre exemplu apăsarea unui buton sau orice alt tip de întrerupere. Consumul de putere când este oprit (ceasul și perifericele oprite) sunt de doar câțiva nW, făcând microcontrolerele eficiente pentru aplicații de durata pe baterii. Alte microcontrolere pot avea funcții speciale, cum ar fi procesoarele digitale de semnal, ce necesită frecvențe mai mari de ceas și consum de putere mai mare.
Istoric
Primul microprocesor a fost Intel 4004, un procesor pe 4 biți, lansat în 1971, cu procesorul Intel 8008 și alte microprocesoare mai capabile apărând în anii următori. Aceste procesoare necesitau cipuri externe pentru a putea fi implementat un sistem funcțional, mărind costurile și făcând imposibilă computerizarea electrocasnicelor.
Primul microcontroler a fost creat cu succes în anul 1971 de către inginerii Gary Boone și Michael Cochran. Rezultatul succesului lor a fost TMS 1000 ce a devenit disponibil comercial în anul 1974. Acesta combina o memorie RAM, o memorie ROM, un ceas și un procesor pe un singur cip, și era dezvoltat pentru aplicații integrate.
Ca răspuns la existența cipului TMS 1000, Intel a dezvoltat un sistem de calculator pe un cip, optimizat pentru aplicații de control, numit Intel 8048, cu primele versiuni fiind comercializate în anul 1977. Acesta combina o memorie RAM și o memorie ROM pe un singur cip.
Majoritatea microcontrolerelor din această perioadă erau construite în două variante. Una avea o memorie de program reprogramabilă EPROM, cu o fereastră de cuarț pe suprafața cipului pentru ca programul din memorie să poată fi șters prin expunere la radiații ultra-violet. Cealaltă variantă avea o memorie PROM ce putea fi programată o singură dată; uneori era adăugată semnificația OTP. Memoria PROM și memoria EPROM erau de fapt identice, dar deoarece memoria PROM nu avea ecranul de cuarț nu exista nici o metodă de expunere la raze ultra-violete prin care să se facă ștergerea memoriei.
În 1993, prin introducerea memoriei EEPROM, a fost permis microcontrolerelor ( începând cu microcontrolerul PIC16x84 de la Microchip) să poată fi șterse rapid, electronic fără împachetarea scumpă necesitată de memoriile EPROM, permițând astfel construcția de prototipuri și programarea după ce cipul a fost introdus într-un sistem. În același an AVR a introdus primul microcontroler ce utiliza memorie flash, un tip special de memorie EEPROM.
AVR Atmel
AVR-ul este un microcontroler bazat pe o arhitectură Harvard RISC modificată pe 8 biți pe un singur chip, dezvoltată de Atmel în anul 1996. AVR a fost unul din primele familii de microcontrolere care să utilizeze memorii flash integrate pe cip.
AVR-ul este o mașinărie cu arhitectură Harvard modificată, în care programul și datele sunt stocate în sisteme de memorii fizice separate, ce apar la adrese diferite, dar au abilitatea de a citi din memoria de program utilizând instrucțiuni speciale.
Familiile de bază ale procesoarelor AVR sunt:
tinyAVR (seria ATtiny) cu următoarele caracteristici:
0,5-16kB memorie de program;
6-32 de pini pe capsulă;
Set limitat de periferice;
megaAVR (seria ATmega) cu următoarele caracteristici:
4-512kB memorie de program;
28-100 de pini pe capsulă;
Set extins de instrucțiuni (multiplicare și instrucțiuni pentru gestionarea unei memorii de program mărite);
Set extensiv de periferice;
XMEGA (seria ATxmega) cu următoarele caracteristici:
16-384kB memorie de program;
44-64-100 de pini pe capsulă;
Dotări extensive pentru performanță, cum ar fi „Sistemul de evenimente” și suport pentru criptografie;
Set extensiv de periferice ce include ADC-uri;
AVR specific pentru anumite aplicații:
Fac parte din seria ATmega, dar cu dotări speciale ce nu se găsesc la ceilalți membrii ai familiei AVR, cum ar fi controler LCD, controler USB, modul PWM avansat, etc.;
Arhitectura dispozitivului
Memorii flash, EEPROM și SRAM se găsesc integrate pe un singur cip, eliminând necesitatea unei memorii externe în majoritatea aplicațiilor. Unele dispozitive dispun de magistrale paralele ce permit adăugarea unor memorii de date adiționale sau dispozitive de memorie. Aproape toate dispozitivele (exceptând cele mai mici cipuri ale familiei TinyAVR) au interfețe seriale, ce pot fi utilizate pentru a conecta memorii EEPROM mai mari sau cipuri flash.
Memoria de program
Instrucțiunile de program sunt stocate într-o memorie non-volatilă de tip flash. Deși microcontrolerul funcționează pe 8 biți, fiecare instrucțiune este scrisă pe unul sau două cuvinte de 16 biți. Dimensiunea memoriei de program este de obicei regăsită în numele dispozitivului (de exemplu ATmega64x are o memorie de program de 64kB, ATmega32x are o memorie de program de 32kB, etc.).
Nu există prevederi pentru memorii în afara cipului, tot codul ce urmează a fi executat de microcontroler fiind necesar să existe în întregime pe memoria integrată în cip.
Memoria de date
Adresele locațiilor de date constau în registrele fișierelor, registrele intrărilor și ieșirilor și SRAM.
Registrele interne
AVR-urile au 32 de registre de un singur bit și sunt clasificate drept dispozitive RISC pe 8 biți. În variantele tinyAVR și megaAVR registrele funcționale sunt primele 32 adrese de memorie (000016-001F16), urmat de 64 de registrele pentru dispozitivele de intrare/ieșire (002016-005F16). În dispozitivele cu multe periferice, aceste registre sunt urmate de 160 de registre de tipul„dispozitive extinse de intrare/ieșire” (006016-00FF16).
SRAM-ul pornește imediat după aceste registre, de la adresa 006016, sau în cazul în care avem „dispozitive extinse de intrare/ieșire” acesta începe la 010016.
Chiar dacă există metode separate de adresare și operații optimizate pentru accesul registrelor și primele 64 de registre de intrare/ieșire, toate adresele pot fi accesate și manipulate ca și cum ar fi în SRAM. Cele mai mici microcontrolere din familia tinyAVR utilizează o arhitectură redusă ce are doar 16 registre (r0-r15) ce nu sunt adresabile ca locații de memorie. Locațiile de memorie ale dispozitivelor de intrare/ieșire încep la adresa 000016 urmate de SRAM. Adițional aceste dispozitive au o deviație mică față de setul de instrucțiuni standard AVR.
Interfețe de programare
Există multe metode de a încărca codul programului pe un cip AVR. Metodele de programare variază de la o familie la alta.
ISP
Această metodă este funcțional executată utilizând SPI, cu câteva modificări pe linia de RESET. Atâta timp cât pinii SPI ai AVR-ului nu sunt conectați la nimic distructiv, cipul AVR poate rămâne lipit pe PCB pe durata reprogramării. Tot ce este necesar este un conector cu 6 pini și un adaptor de programare. Aceasta este cea mai comună metodă de dezvoltare AVR.
Programarea ISP înseamnă posibilitatea de a programa procesorul fără a-l demonta din circuit; există și varianta programării separate, prin scoaterea din soclu și montarea în soclul unui programator dedicat.
Programarea ISP presupune existența a 2 componente:
1) circuitul de programare (programatorul), care se conectează la mufa ISP a plăcuței și la portul serial/paralel/USB al PC-ului;
2) soft-ul de programare, care preia fișierul utilizator și îl transmite programatorului. Trebuie să fie compatibil cu acesta din urmă.
Există mai multe variante:
a) programarea directă din CodeVision; în acest caz, trebuie folosit un programator suportat de CV, configurat din meniul Settings->Programmer; dintre acestea, posibilitățile cele mai întâlnite sunt:
• STK500/AVRISP; acesta este un programator “industrial” care conține el însuși un microcontroler care implementează toată logica de programare; se conectează la PC pe portul serial (sau eventual USB).
• STK200/300; cu acesta este compatibil un programator simplu care se conectează pe portul paralel; programatorul nu conține “inteligență” deci toate semnalele, cu timing-urile lor precise, sunt generate de către softul de programare.
b) programarea folosind un soft extern față de CodeVision. Un exemplu este Pony Prog (www.lancos.com). Suportă atât programatorul paralel, cât și unul serial.
Bootloader
Majoritatea modulelor AVR pot rezerva o zonă specială pentru bootloader, între 4 și 256 kB, unde se află codul ce urmează a fi reprogramat. La resetare, bootloader-ul rulează primul și in funcție de anumite condiții pre-determinate de programator decide dacă să reprogrameze cipul sau să sară la codul deja existent. Codul poate reprograma prin orice interfață disponibilă.
Capitolul V Controlerul ULN2003A
Cipul ULN2003A este o matrice de 7 tranzistoare Darlington de tip NPN capabile de a genera 500mA, 50V la ieșire. Posedă diode flyback cu catod comun pentru comutarea sarcinilor inductive.
Tranzistorul Darlington
Un tranzistor Darlington (cunoscut și sub numele de configurație Darlington, sau pereche Darlington) obține o amplificare în curent foarte mare, conectând doua tranzistoare bipolare în cuplaj direct de curent continuu astfel încât curentul să fie amplificat de primul tranzistor, urmând sa fie amplificat și de către al doilea. Câștigul total în curent va fi produsul câștigurilor celor două tranzistoare: βtotal=β1*β2. Cele 7 perechi din ULN2003A pot opera independent, cu excepția celor are căror colector sunt legate direct la diode.
Specificații
ULN2003 este cunoscut pentru capacitățile sale mărite în curent și tensiune. Controlerele pot fi conectate în paralel pentru a mări curentul de ieșire. Aceasta se poate face efectiv punând un cip peste altul. În general poate fi utilizat pentru interfațarea cu motoare pas cu pas, motorul necesitând curenți mari ce nu pot fi oferiți de alte dispozitive de control.
Specificațiile principale sunt:
500mA curent de colector;
50V tensiune de ieșire;
Include diode flyback;
Intrări compatibile cu modulul TTL și logica CMOS de 5V.
Aplicații
Utilizările tipice pentru ULN2003A sunt de a controla relee, ecrane cu led-uri sau lămpi, motoare pas cu pas.
Capitolul VI Brațul
În acest capitol se va pune accent pe realizarea fizică a brațului mecanic, cu toți pașii construcției acestuia.
Scheletul
Șasiul brațului sau scheletul este o structura complet metalică, construită din piese ce aparțin de firma MECCANO ERECTOR.
Primul pas al construcției propriu-zise a fost dezvoltarea sistemului de pârghie utilizat în sistemul de închidere al degetelor. Inspirația pentru mecanismul utilizat fiind un model dezvoltat de către Paul Ventimiglia împreună cu prof. Taskin Padir și prof. Jerome Schaufeld.
Schema originală care îi aparține lui Paul Ventimiglia este următoarea:
Figura 6.1: Test de mobilitate a unui deget format din 3 piese mobile. (referința 9)
Aceasta a fost sursa de inspirație pentru sistemul de pârghii modificat pe care îl utilizez în implementarea brațului mecanic. După definitivarea mecanismului degetelor următorul pas a fost construcția platformei de montare a degetelor. Numărul final de degete pentru acest braț este de trei degete, în primul rând datorită dimensiunii degetelor, brațul devenind prea greu pentru utilizare fără un exoschelet complet. Al doilea motiv pentru alegerea unui număr de trei degete este numărul limitat de porturi pe microcontroler.
Degetele sunt formate din 3 componente mobile. Două falange și o pârghie centrală ce permite închiderea degetelor utilizând un număr minim de componente mobile.
Pentru conectarea degetelor la motor s-a folosit un sistem de roată dințată cu „melc” pentru a oferi un transfer de cuplu optim. Roata dințată este conectată direct pe deget utilizându-se șuruburi. Acest sistem de transmisie a puterii de la motor la deget este valabil pentru două dintre degete, cel opozabil utilizând un sistem de roți dințate directe, fără „melc”. Degetul opozabil nu are nici o componenta mobilă, nefiind necesară o mobilitate foarte mare în acest stadiu al proiectului.
După ce a fost terminată etapa de planificare și construcție a degetelor, a urmat atașarea acestora pe șasiul palmei. Degetele au fost montate utilizându-se suporturi triunghiulare în formă de L. Aceste suporturi oferă distanțiere suficientă astfel încât roțile dințate să nu atingă șasiul.
Palma a fost concepută pentru a putea acoperi majoritatea componentelor electronice, fără a apărea probleme termice. Posibilele probleme termice au fost eliminate utilizând plăci metalice perforate, ce au rol dublu: circulație mai bună a aerului și greutate totală redusă a șasiului.
În extensia palmei a fost montat un șasiu metalic cu rolul de modalitate de fixare a brațului mecanic pe brațul utilizatorului. În interiorul acestei extensii se găsește consola de control a degetelor. Această consolă conține butoanele aferente fiecărui deget pentru controlul direct. De asemenea pe partea interioară a acestei extensii au fost montate două zone cu burete, pentru a asigura o priză fixă și confortabilă, în același timp asigurând că utilizatorul nu va fi vătămat de marginile ascuțite.
Schema electrică
Pentru dezvoltarea schemei electrice s-a plecat de la modelul proiectului 2, obținându-se următoarea schemă:
R1 și C7 formează circuitul de resetare. În momentul aplicării VCC, C7 este descărcat și „trage” RESET în „0”, resetând procesorul. Ulterior, condensatorul se va încărca prin R1 și linia va sta în „1” (procesul este asimptotic, dar sfârșitul încărcării se consideră după un timp aproximativ egal cu 5*R1*C7). Acest RESET este necesar pentru a asigura pornirea în bune condiții a procesorului. În lipsa lui, tensiunile tranzitorii care apar în momentul alimentării pot duce la ajungerea procesorului într-o stare incertă. Practic, linia RESET e ținută în „0” un timp semnificativ mai lung decât are nevoie sursa de alimentare să intre în regim staționar.
Condensatoarele C1 și C4 au fost conectate cat mai aproape de procesor, între pinii 10-11, respectiv 30-31. Ele sunt condensatoare de decuplare, și sunt specifice oricărui circuit digital, asigură o rezervă de energie în momentul comutării, și astfel previne apariția zgomotului de comutare pe liniile de alimentare.
Cristalul de cuarț, împreună cu condensatoarele C2, C3 și cu amplificatorul intern de la bornele XTAL1 și XTAL2 formează un oscilator cu cuarț. Aceste componente au fost lipite, de asemenea cât mai aproape de pinii respectivi ai procesorului.
Pentru alimentare se folosește stabilizatorul IC2 cu 3 terminale (7805), două condensatoare C5 și C6 de 100nF necesare pentru stabilitatea funcționării acestuia, și dioda D1 care protejează la alimentarea inversă.
Dioda LED este poziționată astfel încât se aprinde când PD6 este pe „1” logic. Rezistența R2 asigură limitarea curentului prin LED la circa (5-1,6)/330=10mA. De notat că în multe cazuri când se conectează un LED la ieșirea unui circuit digital, fără tranzistor de comandă, el se montează invers ( între pinul circuitului si VCC, cu anodul la VCC), întrucât majoritatea circuitelor suportă un curent mai mare când pinul este în „0” logic decât atunci când este în „1” logic.
Butonul SW1 leagă PD5 la masă („0” logic) în momentul apăsării. Întrucât, atunci când nu este apăsat, starea pinului PD5 nu este definită, va trebui activată o rezistență de pull-up intern prin software.
Figura 6.3: Schema finală a proiectului, fără legăturile la motoare, executată în EAGLE
În figura 6.3 este ilustrată schema electrică finală, ce conține toate firele și butoanele necesare execuției proiectului. În figura curentă nu au fost introduse firele ce leagă controlerul ULN2003A de microcontroler deoarece acești conectori nu au fost disponibili în versiunea gratis a softului EAGLE.
În urma utilizării programului EAGLE a fost posibilă obținerea unei scheme de PCB. Această schema este ilustrată în figura 15. Schema PCB-ului a fost obținută din schema electrică anterioară, utilizând funcția de auto-rutare, disponibila în versiunea gratis a programului EAGLE.
Figura 6.4: Schema PCB obținută din programul EAGLE, utilizându-se funcția de auto-rutare.
Interfațarea microcontroler-PC
În cadrul proiectului curent s-a utilizat metoda unei legături seriale directe, utilizând convertorul de nivel MAX232.
Figura 6.5: Convertorul de nivel MAX232
Standardul RS232 prevede o tensiune între +6V~+15V față de masă pentru „0” logic și de -6V~ -15V față de masă pentru „1” logic. Se observă că logica este inversată și sunt necesare tensiuni negative, care nu sunt furnizate direct de către sursa de alimentare. În figura de mai jos este reprezentată forma de undă TTL și respectiv RS232 pentru octetul „01010101”.
Figura 6.6. Forme de undă la intrarea (TTL) și la ieșirea convertorului MAX232/MAX202 (RS232)
Cei 8 biți de date sunt încadrați de un bit de start, care va fi întotdeauna „0”, și un bit de stop, care va fi întotdeauna „1”. Pe figura 6.6 se observă că bitul „1” de stop durează mult mai mult decât ceilalți biți, dar aceasta se întâmplă pentru că, în absența datelor, linia este ținută în „1” logic, deci după ce se transmite acest bit „1” starea liniei nu se schimbă, până la transmiterea unui nou octet, care va începe cu un nou bit de start „0”.
Biții de stop și de start garantează faptul că la începutul fiecărui octet are loc o tranziție „1>0”, chiar și în cazul în care octeții transmiși reprezintă șiruri de „1” sau de „0”. Dezavantajul este că la fiecare 8 biți de date trebuie adăugați cei 2 biți, adică eficiența transmisiei este de doar 80%.
Pinii RxD, TxD ai procesorului se conectează la pinii cu același nume ai convertorului de nivel realizat cu circuitul MAX232. Rolul acestuia este să convertească nivelurile TTL (0…5V) în niveluri RS232, și viceversa; practic, tensiunile +10V și -10V se obțin prin dublarea tensiunii de alimentare a circuitului, folosind un convertor intern cu capacități comutate, care folosește condensatoarele externe C8-C11.
Funcționarea este următoarea: în interiorul circuitului există un grup de comutatoare și o logică de comandă, prin care condensatoarele se încarcă mai întâi la 5V și apoi se pun în serie. Astfel se obține tensiunea de 10V. Prin conectarea inversă se obține -10V (bornele la care sunt legate C8, C10 sunt „flotante” deci comutatoarele interne se pot conecta în orice sens). Schema este dată in figura 6.5.
Verificarea funcționării acestui circuit în regim static s-a făcut măsurând cu voltmetrul tensiunile de pe pinii 2 și 6, față de masă. S-a obținut o tensiune de +8,64V pe pinul 2 și -8,66 pe pinul 6. Aceste valori sunt corespunzătoare pentru modul RS232. Dublarea tensiunii la valoarea de 10V se obține numai în cazul ideal și anume în gol. În sarcină tensiunea este mai mică, dar suficientă pentru a respecta standardul. Pe pinii de date, în pauzele dintre transmisii, trebuie să se măsoare „1”, adică +5V pe TTL și circa -10V pe RS232 (logică inversată).
Mufa DB9 de tip mamă este cablată după standardul DCE, așa cum este ilustrat în Tabelul 6.1. Aceasta înseamnă că se va folosi un cablu serial direct (1 la 1) pentru conectarea la PC, care este echipat cu o mufă de tip tată, cablată după standardul DTE, la care pinii 2 și 3 sunt inversați.
Tabelul 6.1: Tabelul de conectare al pinilor la mufa DB9 mamă
Pentru depanarea portului serial s-a utilizat un osciloscop cu care să se vizualizeze formele de undă în mai multe puncte. Pentru 9600 biți pe secundă un caracter are 10 biți deci durează:
10 biți * 1/9600 sec/bit ≈ 1ms
Pentru ca un caracter (10 biți ) să ocupe toate cele 10 diviziuni pe ecran, determinăm CX:
TX=NX*CX → CX=TX/NX=1ms/10 div=0.1ms/div
S-a ținut apăsată o tastă pe tastatura PC-ului (după ce a fost pornit programul de terminal). Folosind softul de test, macheta a trimis înapoi caracterul următor: microcontrolerul a primit caracterul „e” și a returnat caracterul „f”.
Ordinea evenimentelor urmărită pe osciloscop a fost următoarea:
De la PC, folosind terminalul, s-a emis un caracter (RS232);
Caracterul ajunge pe DB9.2 (nivel RS232), apoi la intrarea în MAX232 (pinul 13);
Este convertit de MAX232 în nivel TTL și scos la ieșire (pinul 12);
Ajunge la procesor (pin 14);
Acesta trimite caracterul cu codul imediat următor (procesor pin 15), ajunge la intrarea MAX232 (pin 11, nivel TTL);
Este convertit în nivel RS232 (MAX232 pin 14) ;
Ajunge pe DB9.3 și de acolo direct către PC.
Interfațarea microcontroler-motor
Pentru proiectul curent, interfațarea microcontroler-motor a fost făcută utilizând controlerele de motor ULN2003A. În figura 6.7 este ilustrată plăcuța ce înglobează sistemul de conectare microcontroler-motor cu controlerul ULN2003A.
Au fost utilizate în total 3 astfel de plăcuțe pentru conectarea celor trei motoare la microcontroler.
Metoda de conectare este următoarea:
Conectarea celor 4 intrări ale plăcuței la microcontroler, fiecare intrare corespunzând unui bobinaj din interiorul motorului pas cu pas;
Pinii la care au fost conectate motoarele sunt următorii:
Pinii 22, 23, 24, 25 (PC0, PC1, PC2, PC3) sunt responsabili pentru controlul motorului 1, echivalentul degetului arătător;
Pinii 26, 27, 28, 29 (PC4, PC5, PC6, PC7) sunt responsabili pentru controlul motorului 2, echivalentul degetului mic;
Pinii 1, 2, 4, 5 (PB0, PB1, PB3, PB4) sunt responsabili pentru controlul motorului 3, echivalentul degetului mare;
Pinii VCC respectiv GND ai plăcuțelor se conectează direct la linia de alimentare +12V, respectiv linia de masă a plăcii;
Plăcuțele se conectează direct de motoare prin intermediul mufelor deja montate după cum este ilustrat în figura 6.8;
Figura 6.8: Legătura directă plăcuță de control, motor
Alegerea motoarelor și montarea acestora
Alegerea motoarelor a fost făcută după următoarele criterii:
Greutate;
Cuplul;
Tensiunea de alimentare necesară;
Volum;
Dimensiunile axului;
Tipul motorului;
Lungimea cablurilor;
Ținând seama de toate aceste criterii a fost ales următorul model de motor: MingJong ST28.
Specificațiile principale ale acestui motor sunt:
Rezistență: 280Ω;
Tensiune de alimentare: 12V;
Curent: 32mA;
Impedanță: 380Ω;
Numărul de faze: 4;
Unghiul per pas: 5,625 grade;
Rată de reducție: 1/64;
Zgomot: 40dB;
Conector terminal: JST SPH-002T-P0.5S
Figura 6.9: Motorul MingJong ST28 (referința 11)
Printre avantajele prezentate de acest motor se numără: compatibilitatea conectorului cu controlerul ULN2003A, gabarit redus astfel permițând o mobilitate sporită, necesitatea unei tensiuni de alimentare de nivel mediu (se poate utiliza o baterie de tipul Li-Ion cu 3 celule, bateria având o densitate de energie suficient de mare pentru a permite funcționarea brațului în mod independent, fără a fi conectat la o sursă de alimentare fixă), lungimea conectorului de 420mm, unghi per pas redus astfel oferind un control excelent asupra mișcărilor degetelor.
Pentru montarea acestor motoare pe șasiu a fost utilizat un mecanism de prindere pe bază de șuruburi, în cazul unei posibile defecțiuni zona fiind ușor accesibilă și motorul poate fi înlocuit cu ușurință.
Forma axului acestor motoare a permis o montare „solidă” a sistemului de transmisie. Sistemul de transmisie constă într-un „melc” metalic, montat direct pe axul motorului, ce va pune în mișcare roata dințată ce este montată pe deget. Astfel sunt utilizate două reductoare: reductorul intern de 1/64, și reductorul extern format din sistemul de transmisie „melc”- roată dințată cu rata de reducție de 1/30; Prin utilizarea acestor două sisteme de reducție se obține cuplul necesar pentru a putea pune în mișcare ansamblul mecanic al degetelor.
În figura 6.10 este ilustrat mecanismul utilizat, din diferite unghiuri, corespunzătoare figurilor 6.10a și 6.10b.
Figura 6.10: a) ansamblul de transmisie observat pe două dintre degete
b) ansamblul de transmisie observat pe toate cele trei degete;
În figura 6.11 este ilustrat modul de montare al motoarelor, poza fiind făcută din interiorul brațului.
Figura 6.11: Poză din interior a sistemului de montare al motoarelor
Consola de control direct
Consola de control direct este construită pentru a ușura controlul degetelor. Această consolă a fost dezvoltată pentru a putea oferi acces ușor la cele 6 butoane necesare controlului degetelor. Consola este amplasată în centrul de greutate al brațului mecanic pentru a facilita mișcările utilizatorului. De asemenea consola servește și ca componentă necesară purtării brațului mecanic.
Figura 6.12 ilustrează butoanele consolei înainte ca acestea să fie asamblate în forma și poziția finală. Sunt ilustrate toate cele 6 butoane, conectate la placa originală de test.
Figura 6.12: Placa de test cu cele toate legăturile necesare montate.
Sisteme de siguranță
Deoarece nu se dorește strivirea obiectelor ce sunt prinse de către brațul mecanic a fost implementată o limitare de putere, limitarea fiind dată de puterea exercitată de motoare, și de limitările impuse de sistemul mecanic utilizat.
Pe lângă sistemul implementat pentru siguranța obiectelor prinse, au fost implementate și sisteme pentru siguranța utilizatorului. Mai exact, amplasarea componentelor electrice cât mai departe de mâna utilizatorului, utilizarea bureților pentru asigurarea unei prize confortabile, fixe care să nu cauzeze răni.
Capitolul VII Programarea microcontrolerului
Programarea microcontrolerului s-a pornit de la instrucțiunile aferente proiectului 2.
Programarea utilizând bootloader-ul
Programarea clasică a procesorului folosește fie un programator dedicat, fie conectorul ISP la care se conectează un programator.
O varianta mai ieftină și mai comodă este să nu se folosească nici un fel de programator. Pentru aceasta, în flash-ul procesorului se încarcă mai întâi un soft numit bootloader (evident, pentru aceasta trebuie un programator, dar operația se face o singură dată). După aceea, bootloader-ul comunică prin serială cu un program de PC numit PC-loader pentru a transfera softul de aplicație și a-l programa în flash. Prin urmare, odată ce bootloader-ul a fost încărcat, tot ce mai este necesar este un port serial, iar placa noastră de test are deja un port serial construit și conectat la pinii procesorului.
Bootloader-ul se plasează într-o zonă specială a memoriei procesorului, tipic la sfârșitul flash-ului, și nu este suprascris de aplicație, pe care o încarcă de la începutul flash-ului. Cum, de asemenea, dimensiunea sa este mică, cea mai mare parte a memoriei flash rămâne disponibilă pentru aplicație. Practic, bootloader-ul este ca un sistem de operare minimal, care are rolul de încărcare și schimbare a aplicației. Se întâlnesc bootloadere la toate echipamentele care permit schimbarea aplicației din flash, cum sunt multe telefoane mobile, routere, puncte de acces, plăci de bază de PC (pentru schimbarea BIOS-ului), etc. Inclusiv sondele spațiale interplanetare sunt echipate cu un astfel de sistem, pentru a permite efectuarea de corecții în soft, de la distanta. Trebuie găsită o metodă prin care poate fi invocat bootloader-ul, întrucât ne dorim ca el să fie transparent: pe microcontroler trebuie să ruleze aplicația în mod normal, fără interferențe, și să poată folosi portul serial. Sunt mai multe metode pentru a face aceasta; metoda cea mai “elegantă” este ca aplicația sa accepte o anumită comandă pe seriala și în acest caz sa predea controlul bootloader-ului. În cazul bootloader-ului furnizat, s-a ales metoda cea mai simplă, în care aplicația nu trebuie să știe de existența bootloader-ului: el se activează la pornire și verifică dacă PIND.5=0; în acest caz, el rămâne activ și așteaptă să interacționeze cu programul PC-loader. În caz contrar, predă imediat controlul aplicației, deci din punct de vedere al utilizatorului e ca și când n-ar exista. Așadar, pentru a încărca o aplicație (fișier .HEX) se procedează astfel:
– se pornește programul PC-loader, se selectează cu Browse fișierul .HEX dorit; se conectează prin seriala placa de test la PC;
– se ține apăsat butonul de pe placă, conectat la pinul D.5, se aplică alimentarea plăcii, după care se eliberează butonul; se observa ca aplicația din procesor nu pornește (LED-ul nu este aprins, etc); în acest moment controlul a fost preluat de către bootloader, care așteaptă;
– se apasă în PC-loader butonul “Start Upload”; în acest moment bara de progres indică încărcarea aplicației;
– după ce bootloader-ul primește o aplicație, el preda controlul acesteia și își încetează funcționarea. O nouă invocare presupune repetarea pașilor de mai sus.
Dezavantajul acestei metode este că programul bootloader depinde exact de configurația de pe placă; în cazul proiectului curent, procesorul nu poate fi decât AT Mega 16, trebuie sa existe un buton la pinul D.5, și cuarțul trebuie sa aibă exact valoarea specificată. Orice modificare a acestor parametri presupune recompilarea bootloader-ului și re-încărcarea acestuia folosind un programator clasic.
Explicarea codului
Realizarea proiectului (.prj)
În compilator se intră dând Enter pe fișierul .prj (sau deschizând compilatorul si încărcând separat acest fișier din meniul File). Acest fișier conține informațiile necesare editării și compilării proiectului: fișierele sursă, opțiunile de compilare, tipul de procesor din cadrul familiei AVR, etc. Pentru a vizualiza aceste opțiuni, se verifică meniul Project->Configure->C Compiler. Acolo sunt setate toate valorile specifice machetei noastre. De exemplu, funcția „delay_ms” calculează întârzierea pe baza frecvenței ceasului, deci a cuarțului folosit – daca se schimba cuarțul, trebuie actualizat acest parametru. De asemenea, se poate configura ce opțiuni să suporte funcțiile „printf()” și „scanf()”. Pentru a economisi memorie se poate exclude suportul pentru reprezentarea unor tipuri (long sau float) precum și a notației de genul %3d (reprezentare pe 3 cifre) respectiv %3.2f (reprezentare cu 2 cifre după punctul zecimal). Dacă se exclud aceste opțiuni, ele nu trebuie apelate în program, căci compilatorul nu va da erori, dar de afișat nu se va afișa nimic. Tot aici se definește sub ce formă compilatorul va genera codul executabil. Pentru multe microcontrolerele (nu numai AVR) se folosește formatul INTEL HEX care este practic analogul fișierului EXE produs de un compilator pentru Windows. Prin urmare, un proiect este format din următoarele fișiere (în Windows Explorer este recomandat să se de-selecteze opțiunea de ascundere a extensiilor fișierelor, care de multe ori este setată implicit):
• .prj fișierul de definiție a proiectului;
• .c .h fișierele sursa C
• .hex fișierul rezultat în urma compilării, care va trebui încărcat în μC;
• .eep fișierul de inițializare a variabilelor stocate în EEPROM (doar dacă este cazul);
• .obj .rom .a .i .map etc. fișiere temporare de lucru (pot fi ignorate).
CodeVisionAVR include și funcții de programare a μC-ului, astfel încât după ce se execută opțiunea Project->Build All sa fie automat apelat programatorul și să se încarce fișierul .hex rezultat în cip. În cazul acestui proiect însă, nu se folosește această opțiune, întrucât nu există un programator (dispozitiv dedicat), ci încărcarea fișierului se face prin serială folosind programul separat AVRBuster. Dacă apare fereastra de programare, se va închide, și din Project- >Configure se va seta să nu se mai apeleze opțiunea de programare a cipului (“program the chip”) după compilare. Codul propriu-zis se află în fișierele .c si .h. Pentru proiecte de complexitate mai mare de cca. 1-200 de linii este recomandata gruparea funcțiilor în fișiere după rolul îndeplinit de acestea. Fiecare fișier este creat și adăugat în proiect folosind meniul Project->Configure->Files->Add. Pentru a identifica ușor în ce fișier este fiecare funcție este recomandabilă botezarea funcțiilor având ca prefix numele fișierului.
De exemplu funcția Init_initController() se vede după nume că este în fișierul init.c. Funcțiile fără prefix sunt în main.c.
În limbajul C este nevoie ca funcțiile sa aibă prototipuri (declararea funcției, separat de scrierea ei propriu-zisă). Varianta aleasă de mine este includerea acestora în fișierul func.h (indiferent în ce fișiere sunt definite funcțiile propriu-zise); prin adăugarea acestui fișier în proiect compilatorul are la dispoziție toate prototipurile.
Este recomandabila gruparea tuturor definițiilor în fișiere .h; în cazul nostru scopul este îndeplinit de fișierul defs.h. Tot acolo este definită și versiunea programului. De fiecare dată când există o versiune (intermediară) funcționala și s-a dorit trecerea mai departe prin adăugarea sau schimbarea unor facilități, se salvează întreagă structura de fișiere în versiunea curentă, și se continuă prin incrementarea numărului de versiune. În acest fel se poate reveni ulterior, mai ales dacă de la o versiune încolo apare o anumită eroare.
De asemenea, programul poate fi interogat (pe seriala) despre numărul versiunii, așa cum se vede în exemplu (la primirea caracterului ?). Dacă programul nu merge cum trebuie, primul lucru ce se verifică este numărul versiunii – se poate încărca accidental alt fisier .hex decît cel dorit.
Folosirea CodeWizardAVR
Compilatorul CodeVision pune la dispoziție acest tool extrem de util pentru scrierea automată a părții de inițializare a diferitelor registre: timere, întreruperi, serială, watchdog, afișaj LCD etc. Când se rulează CodeWizard, după ce se setează toți parametrii doriți, este recomandabilă folosirea opțiunii File- >Program Preview, din care se vor copia inițializările pentru perifericele dorite. Dacă se folosește opțiunea File->Generate, Save and exit, se suprascrie întregul proiect curent, implicit inițializând tot ce nu este definit cu 0.
Descrierea fișierelor din soft
Se vor descrie linie cu linie fișierele .c si .h din proiect.
Fișierul init.c (conținut în Anexa 1)
Cea mai mare parte a codului generat de CodeWizard este mutat manual aici, în funcția de inițializare Init_initController() care va fi apoi apelată la începutul lui main().
Liniile 12-23:
Fiecare port are 2 registre asociate:
– registrul DDRx (x=A,B,C…) specifică „direcția” fiecărui pin electric al portului X; sunt 8 pini corespunzători celor 8 biți. „1” înseamnă ieșire iar „0” intrare. Inițializarea cu „1” sau „0” are efecte majore la nivel intern (în procesor), practic se comută blocurile corespunzătoare funcțiilor de intrare și ieșire, întrucât procesorul permite utilizatorului să folosească orice pin de port în orice direcție. Trebuie avut grija că daca un pin de port este legat la masă sau la VCC, să nu fie definit ca “output” întrucât s-ar obține efectul unui scurt-circuit. De aceea, registrul DDRx se setează numai consultându-se cu schema machetei în față.
– registrul PORTx are semnificație diferită în funcție de sensul fiecărui pin:
– dacă sensul pinului n este de ieșire (DDRx.n=1), atunci pinul PORTx.n va genera, în logică pozitivă, nivelul de tensiune corespunzător (1=VCC, 0=GND). Curentul maxim ce poate fi consumat din fiecare pin este dat în foaia de catalog.
– daca sensul pinului n este de intrare (DDRx.n=0), aparent nu are sens scrierea unei valori în bitul respectiv. În acest caz însă, prin convenție, scrierea unui „1” în PORTx.n va avea ca efect activarea unei rezistente interne de pull-up pentru acea intrare. Rezistența de pull-up este o rezistență de valoare mare (tipic, 100KΩ) legata între VCC și pin; astfel, când pinul este lăsat în gol, starea sa va fi precis definită ca „1”. Dacă însă se aplică din exterior 0 logic, rezistența nu contează, datorită valorii mari. De obicei se activează pull-up-ul atunci când pinul este legat la un contact care se închide la GND (este și cazul acestui exemplu, în care butonul este legat între port și masă; când butonul este apăsat, portul devine „0”, în rest stă în „1”). Implicit, PORTx.n=0 adică nu există rezistenta de pull-up. Dacă procesorul nu ar dispune de aceasta facilitate, ar trebui adăugată manual o rezistenta externa de 100K către VCC. De remarcat că scrierea în binar a celor 8 biți este în ordinea PORTx = 0bB7B6B5B4B3B2B1B0
Aici sunt definite porturile în următorul mod:
Pinii 1, 2, 4, 5 ai microcontrolerului (PB0, PB1, PB3, PB4) sunt definiți ca ieșire, responsabili pentru controlul motorului 3, motorul legat la degetul „mare”. De menționat că se „sare” peste pinul 3 intenționat deoarece la acesta este legată o rezistență internă de „pull-up”.
Pinii 22, 23, 24, 25 (PC0, PC1, PC2, PC3) sunt definiți ca ieșire, responsabili pentru controlul motorului 1, motorul legat la degetul „arătător”.
Pinii 26, 27, 28, 29 (PC4, PC5, PC6, PC7) sunt definiți ca ieșire, responsabili pentru controlul motorului 2, motor legat la degetul „mic”.
Pinii 16, 17, 18 (PD2, PD3, PD4) sunt definiți ca intrări, pe acești pini fiind montate butoanele necesare pentru controlul direct al degetelor.
Liniile 24-66 și 77:
Sunt inițializate registrele timerelor 0,1,2. În cazul proiectului curent se folosește timerul 1 în modul Output Compare A astfel:
• timerul va fi incrementat de ceasul intern al procesorului, divizat cu 1024 de către registrul de pre-scalare intern (factorul de divizare este dat de ultimii 3 biți din registrul TCCR1B, numiți CS12-CS10);
• la atingerea valorii programate de utilizator în registrul OCR1A timerul va fi resetat la 0 (datorită activării modului CTC – Clear Timer on Compare match prin biții WGM13 si WGM12, adică 4 și 3, din TCCR1B). Acesta are ca efect divizarea frecvenței ceasului cu valoarea din registrul de pre-scalare înmulțită cu cea din OCR1A;
• în acest moment se va genera o întrerupere (bitul OCIE1A, adică bitul 4, din TIMSK). Registrul OCR1 este pe 16 biți, dar se accesează sub forma a 2 registre pe 8 biți OCR1AH si OCR1AL. Registrul de pre-scalare este un tip special de registru folosit ca divizor de frecvență mare, de valori puține și fixe (tipic puteri ale lui 2). Deci, el aduce frecvența cuarțului la o frecvență mai mică, care va fi apoi divizată prin registrele timerului, de data asta cu o valoare oarecare, între 1 și valoarea maximă pe 8 sau 16 biți a registrului respectiv.
Modul de calcul al registrului OCR1A:
Frecvența ceasului de 7.3728MHz divizată cu valoarea registrului de pre-scalare de 1024 este 7200Hz; s-a ales factorul de divizare prin maxim din registru (1024) întrucât dorim să aprindem LEDul cu o frecvența cât mai mică (1Hz) și un timer are doar 16 biți deci factorul maxim de divizare în timer este de 216 = 65536; rezultă că dacă nu am avea registrul de pre-scalare, cu acest timer nu am putea genera o frecvență mai mică de 7.3728MHz/65536 = 123Hz. Observăm de asemenea că valoarea de 7200 nu încape pe 8 biți, deci nu s-ar putea folosi timerele 0 si 2, ci doar 1 care e pe 16 biți (decât dacă am face divizări suplimentare în rutina de întrerupere a timerului).
În cazul nostru, divizam frecvența de 7200Hz cu 7200 pentru a obține 1Hz.
720010= 0x1C2016 deci, OCR1AH = 0x1C, OCRA1L = 0x20
Liniile 68-73:
Se inițializează sistemul de întreruperi externe.
Liniile 79-89:
Se inițializează portul serial (USART – Universal Synchonous/Asynchronous Receiver Transmitter) în modul asincron (UART = standardul RS232, existent pe PC), viteza de 9600bps, 8 biți de date, fără bit de paritate,1 bit de stop. Notația standard este 9600,8,N,1. Nu este necesar nici un calcul, căci CodeWizard face toate calculele pentru acest modul.
Liniile 91-95:
Se inițializează comparatorul analogic.
Liniile 97-102:
Se inițializează Watchdog-ul. Sintaxa este specială (același registru este scris de 2 ori, cu 2 valori diferite; aparent a 2-a instrucțiune anulează efectul primei, dar nu este cazul pentru acest registru). Se folosește conceptul de Timed Access, adică scrierea unei succesiuni de valori într-un registru într-un interval de timp dat, situație des întâlnită în cazul inițializării sistemelor critice, pentru a evita pornirea acestora dintr-o eroare. Dacă Watchdog-ul este pornit accidental într-un program care nu apelează instrucțiunea wdr, acel program nu va mai funcționa, procesorul resetându-se tot timpul.
Fișierul defs.h (conținut în Anexa 2)
Aici se pun toate #define-urile din program cu caracter global. Este recomandabil să se definească și numărul versiunii. Toate constantele numerice se vor defini aici cu nume simbolice. Se observă că inclusiv 1 si 0 sunt definite ca TRUE si FALSE. O parte din definițiile de aici nu sunt folosite (ele provin dintr-un proiect mai mare). Ceea ce se definește și nu se folosește nu ocupă memorie, întrucât definițiile sunt interpretate de pre-procesor, nu de compilator.
Linia 4:
Se definește versiunea curentă a codului scris. Această valoarea este ce se returnează la interogarea pe serială cu caracterul „?”.
Liniile 6-8:
Se definește valoarea de NULL ca fiind 0.
Liniile 10-13:
Se definesc tipurile de date utilizate.
Liniile 15-18:
Se definește sistemul de logică booleană, TRUE fiind corespunzător valorii „1”, FALSE valorii „0” și DUMMY tot valorii „0”.
Linia 23:
Definește Watchdog trigger-ul, folosind funcția wdogtrig().
Liniile 26-28:
Definesc ceasul, frecvența căruia este dată de sistemul extern de oscilator cu cuarț.
Liniile 33-40:
Se definesc următoarele nume ale pinilor pentru simplificarea utilizării:
Pinul 20 (PORTD.6) este denumit LED1, fiind pinul la care este legat LED-ul;
Pinul 19 (PINB.2) este denumit SW1, la acest pin fiind legat butonul ce se ocupă cu schimbarea frecvenței de aprindere a LED-ului;
Pinul 16 (PIND.2) este denumit F1C, la acest pin legându-se la butonul responsabil cu închiderea degetului „arătător”;
Pinul 17 (PIND.3) este denumit F2C, la acest pin legându-se la butonul responsabil cu închiderea degetului „mic”;
Pinul 18 (PIND.4) este denumit F3C, la acest pin legându-se la butonul responsabil cu închiderea degetului „mare”.
Pinul 6 (PINB.5) este denumit F1O, la acest pin legându-se la butonul responsabil cu deschiderea degetului „arătător”;
Pinul 7 (PINB.6) este denumit F2O, la acest pin legându-se la butonul responsabil cu deschiderea degetului „mic”;
Pinul 8 (PINB.7) este denumit F3O, la acest pin legându-se la butonul responsabil cu deschiderea degetului „mare”.
Liniile 45-58:
Aici sunt definite denumirile bobinajelor celor 3 motoare, fiecare motor având un set de 4 bobinaje denumite Ax, Bx, Cx, Dx un „x” este numărul motorului de care aparține. Astfel seturile sunt:
Pinii 22-25 sunt definiți ca setul responsabil pentru controlul motorului 1, set denumit A1, B1, C1, D1;
Pinii 26-29 sunt definiți ca setul responsabil pentru controlul motorului 2, set denumit A2, B2, C2, D2;
Pinii 1,2,4,5 sunt definiți ca setul responsabil pentru controlul motorului 3, set denumit A3 ,B3, C3, D3.
Linia 60:
Această linie este utilizată pentru a include setul prototipurile funcției ce se găsesc în fișierul funct.h.
Fișierul funct.h (conținut în Anexa 3)
Aici se definesc prototipurile funcțiilor folosite. Daca ar fi și alte fișiere în afară de init.c, s-ar include și funcțiile din acestea. În limbajul C prototipurile reprezintă declarațiile funcțiilor, fără corpul acestora. Se folosesc atât pentru a întări verificarea parametrilor (daca este apelată o funcție cu alți parametri decât s-a declarat în prototip, se generează o eroare), cât și pentru a putea folosi funcții care se cheamă reciproc (în care caz, indiferent în ce ordine sunt declarate, una din funcții va fi folosită înainte de a fi declarată, și fără prototip se obține o eroare de tip “funcție nedeclarată”).
Linia 1: este definit prototipul funcției Init_initController();
Fișierul main.c (conținut în Anexa 4)
Este fișierul principal al programului; conține funcția main() și câteva apeluri specifice microcontrolerului, pe care implicit CodeWizard le pune în acest fișier.
Liniile 1-15:
Se includ fișierele de tip header. Între <> sunt headerele de sistem, căutate în directorul de include-uri configurat în CodeVision, iar între „” sunt fișierele .h create pentru acest proiect (din directorul cu proiectul).
Liniile 16-127:
Aceasta parte relativ lungă este generată de CodeWizard deci nu necesită intervenția utilizatorului, și nu vom intra în detalii asupra sa. Scopul ei este definirea funcțiilor seriale ca întreruperi (dacă se bifează Rx Interrupt și Tx Interrupt în Wizard). În acest caz, se definesc înteruperile:
interrupt [USART_TXC] void usart_tx_isr(void)
interrupt [USART_RXC] void usart_rx_isr(void)
folosind cuvântul-cheie interrupt. În cazul în care nu se folosește varianta pe întreruperi, aceasta parte nu apare, și se includ funcțiile din librării (dar funcțiile seriale sunt mult mai puțin eficiente, consumând mult timp de așteptare). Faptul că se folosesc funcțiile bazate pe întreruperi și nu cele din librării este “semnalat” de compilator prin definițiile _ALTERNATE_PUTCHAR_ și _ALTERNATE_GETCHAR_ .
Rezultatul este că se pot folosi funcțiile standard de I/O din C (funcțiile de bază sunt putchar(), getchar() iar funcțiile derivate din acestea sunt printf(), scanf() și celelalte asemenea). În plus, variabila globală rx_counter conține numărul de caractere recepționate, și poate fi interogată de programul utilizator. În cazul unui program pe PC, aceste funcții folosesc terminalul (ecranul și tastatura). În cazul programului pe microcontroler, ele folosesc portul serial al acestuia. Prin folosirea pe PC a unui program de Terminal (fie cel inclus în CodeVision, fie altul cum ar fi HyperTerminal) și conectarea microcontrolerului la portul serial al PC-ului, se obține aproximativ același rezultat: tot ce scrie programul din microcontroler apare pe ecranul terminalului, și tot ce scrie utilizatorul este trimis către microcontroler. Deci, e ca și când placa noastră cu μC ar avea tastatură și ecran.
Existenta acestor funcții face mult mai ușor debugging-ul, și permite comunicarea ușoară între utilizator și microcontroler, de exemplu pentru a seta parametri, a da comenzi, etc. Este posibilă în acest mod și folosirea unui Bootloader, un program rezident în Flash care permite încărcarea soft-ului principal fără a mai fi nevoie de un programator extern conectat la pinii de ISP. Folosind ISP se încarcă o singura dată Bootloader-ul, după care softul se încarcă de oricâte ori direct pe serială, prin comunicarea cu un program PcLoader care rulează pe PC și știe să comunice cu Bootloader-ul.
Liniile 130-136:
Se definește rutina de servire a întreruperii timerului 1 (ISR – Interrupt Service Routine). Inițializarea acestuia se face în init.c. Numărătorul timer-ului este incrementat la fiecare impuls de la ieșirea registrului de pre-scalare respectiv; când are loc evenimentul “output compare match A” (valoarea din numărător ajunge la valoarea presetată de utilizator în registrul OCR1A) procesorul generează o întrerupere, în cazul nostru la 1 secundă, care apelează automat aceasta funcție. În cazul nostru singura acțiune efectuată este inversarea stării LEDului – simbolul tilda (~). Definirea portului LED-ului este făcută în defs.h. Se observă că rutina de întrerupere este definită cu o sintaxă specială: „interrupt [TIM1_COMPA] void nume_functie(void)” adică, funcția nume_functie() va fi apelată când are loc întreruperea TIM1_COMPA.
Liniile 144-286:
Aici sunt definite funcțiile utilizate pentru mișcarea celor 3 motoare, în total fiind utilizate 6 funcții cu următoarele denumiri:
STEPPERCW1: este funcția ce controlează motorul 1, generând mișcarea axului în sens trigonometric;
STEPPERCCW1: este funcția ce controlează motorul 1, generând mișcarea axului în sens invers trigonometric;
STEPPERCW2: este funcția ce controlează motorul 2, generând mișcarea axului în sens trigonometric;
STEPPERCCW2: este funcția ce controlează motorul 2, generând mișcarea axului în sens invers trigonometric;
STEPPERCW3: este funcția ce controlează motorul 3, generând mișcarea axului în sens trigonometric;
STEPPERCCW3: este funcția ce controlează motorul 3, generând mișcarea axului în sens invers trigonometric;
Denumirile STEPPERCW și STEPPERCCW au fost date sugestiv, STEPPERCW însemnând „Stepper Clockwise” adică mișcare în sensul acelor de ceas, iar STEPPERCCW însemnând „Stepper Counter ClockWise” adică mișcare în sensul invers acelor de ceas. Aceste funcții generează mișcările de închidere și deschidere a degetelor.
Liniile 289-314:
Începutul funcției main(); aici se vor pune inițializările; se face activarea întreruperilor care implicit sunt dezactivate.
Prin valori inițiale se înțeleg valorile de plecare ale variabilelor ce urmează a fi utilizate mai departe în program. Variabilele inițializate în această secțiune de cod sunt:
LED1=1; această linie inițializează starea LED-ul montat pe placă, acesta fiind aprins;
Seturile A1=0, B1=0, C1=0, D1=0 sunt valorile inițiale ale bobinajelor motorului 1, aceste inițializări nu sunt absolut necesare, dar sunt trecute pentru a se asigura buna funcționare a programului;
Seturile A2=0, B2=0, C2=0, D2=0 sunt valorile inițiale ale bobinajelor motorului 2;
Seturile A3=0, B3=0, C3=0, D3=0 sunt valorile inițiale ale bobinajelor motorului 3;
La sfârșitul acestei secțiuni se intră în buclă infinită care reprezintă funcționarea propriu-zisă a programului.
Linia 319:
Se apelează în buclă (folosind definiția din defs.h) instrucțiunea wdr a procesorului, definită ca wdogtrig() în defs.h, care înseamnă “watchdog reset”. Watchdog-ul, literalmente un “câine de pază”, este un accesoriu extrem de util unui sistem cu microprocesor; din fericire AVR are unul inclus pe cip, în caz contrar, pentru alte procesoare, fiind utilă includerea în sistem a unui cip special de watchdog. Watchdog-ul este în esență un sistem care resetează procesorul după un anumit timp (configurabil, dar de obicei nu mai mare de câteva secunde) în cazul nedorit când programul se blochează. Blocarea poate interveni din vina programatorului (o situație neprevăzută care introduce programul într-o buclă din care nu poate ieși), sau din cauze externe, de exemplu o eroare pe sursa de alimentare. În esență, watchdogul este un temporizator a cărui expirare duce la generarea semnalului RESET pentru procesor. Logica de watchdog este realizată într-o porțiune a procesorului care nu este afectată de program. În timpul funcționarii normale, programul (programatorul) trebuie să apeleze funcția de anulare a watchdogului la intervale oricât de mici, dar nu mai mari decât intervalul maxim la care a fost setat să expire temporizatorul. Trebuie avut în vedere watchdogul în situațiile în care se așteaptă input de la utilizator; nu este permisă nici în acest caz depășirea intervalului de temporizare; dacă se așteaptă de exemplu date pe termen nedefinit (cum ar fi așteptarea ca utilizatorul sa tasteze ceva) intervalul de așteptare trebuie partiționat în intervale de watchdog.
Dacă watchdog-ul este pornit și nu se apelează instrucțiunea wdogtrig(), procesorul se va reseta la fiecare circa 2 secunde, aparent fără motiv.
Liniile 324-582:
Această porțiune de cod are rolul de a controla motoarele via butoanele consolei de control direct. A fost implementat un mod de control direct, utilizând 6 butoane, câte două butoane asociate fiecărui deget. Aceste butoane îndeplinesc funcții simple, mai exact funcțiile de închidere și deschidere a degetelor, de asemenea fiind adăugate cazuri pentru apăsarea simultană a mai multor butoane. De asemenea este adăugată și condiția în care nici un buton nu este apăsat. În acest caz toate valorile bobinajelor se vor întoarce la „0”.
Liniile 584-591:
Existența unui caracter primit pe serială de la utilizator este detectată în variabila rx_counter. Caracterul va fi citit cu getchar(). Se introduce valoarea citită în temp întrucât nu se poate apela aceasta funcție de 2 ori (s-ar citi caractere diferite).
Liniile 593-610:
Citirea tastei se face folosind o procedură specială numită debouncing. (to bounce= a ricoșa, a sări pe rând între mai multe poziții). Ideea este că un contact electromecanic se poate închide și deschide de mai multe ori în primele milisecunde corespunzătoare apăsării și eliberării butonului, datorită imperfecțiunii sistemului mecanic și a defectelor microscopice de pe suprafețele metalice care vin în contact. De aceea, în anumite situații, este posibil ca programul sa treacă suficient de des printr-o buclă (câteva milisecunde pot reprezenta un timp foarte lung pentru un procesor care rulează la câțiva MIPS) încât să detecteze, în mod eronat, că utilizatorul a apăsat tasta de mai multe ori. Pentru a preveni această posibilitate, în cazul detectării că s-a apăsat tasta, se va aștepta un timp de ordinul zecilor de ms și se va mai verifica o dată; metoda folosită în program nu este cea mai eficienta (funcția delay_ms() este cu așteptare în buclă, în acest timp procesorul nu mai executa alte instrucțiuni); se pot imagina și alte metode de debouncing software. De notat că la unele sisteme debouncing-ul se face prin hardware, prin adăugarea unor bistabili sau a altor circuite între tastă și intrarea în procesor.
De asemenea, se introduce o buclă while suplimentară, pentru a aștepta ca utilizatorul să elibereze tasta, similar cu acțiunea mouse-ului în windows, când nu apăsarea, ci eliberarea butonului este ceea ce duce la îndeplinirea acțiunii. În așteptarea eliberării, trebuie apelat wdogtrig(), altfel o apăsare mai lungă ar duce la resetarea μC-ului.
La fiecare apăsare de tastă, se schimbă între 2 seturi de valori ale registrelor timerului 1, modificând condiția care generează întreruperea de timer.
Codul se încheie cu închiderea tuturor buclelor rămase deschise, incluzând while-ul permanent și bucla main().
Capitolul VIII Rezultatele testelor
De-a lungul construcției brațului au fost întâmpinate multiple probleme, de natură mecanică și electrică. În acest capitol vor fi exemplificate problemele întâlnite și modurile de soluționare al acestora.
Printre primele probleme întâmpinate nu au fost cele mecanice sau electrice, ci problemele de dimensiune și greutate. Din aceste considerente s-a ales reducerea numărului de degete de la 5 la 3, reducând astfel greutatea și dimensiunea totală considerabil.
Prima problemă mecanică întâmpinată după asamblarea preliminară a șasiului a fost existența unui joc mecanic relativ mare, acest joc mecanic cauzând roțile dințate să își mărească distanța străbătută până la „melc” cauzând defectarea sistemului de transmisie și distrugerea dentiției roților. Această problemă a fost rezolvată prin utilizarea unor traverse metalice, înlocuirea sistemului original de transmisie din plastic cu unul format din piese metalice, utilizarea unor motoare cu joc mecanic al axului cât mai mic posibil și a unui sistem de pârghie mai bun pentru sistemul de mișcare al degetelor.
Printre problemele electrice apărute în decursul testărilor au fost:
funcționarea necoerentă a butoanelor, rezolvată prin implementarea mecanicii de debounce-ing;
lipsa mișcării motoarelor, datorate unui curent insuficient prin bobinajele interne, problemă rezolvată prin crearea unei linii separate de alimentare utilizând direct sursele de alimentare din laborator, setate să genereze o tensiune de 30V;
mișcări necoerente ale motoarelor datorate codului eronat, probleme rezolvate prin teste multiple.
Testele făcute în laborator au avut următoarele rezultate:
#1. Mișcarea completă a degetelor, exemplificată prin figurile 24 și 25.
Figura 8.1: Brațul mecanic cu pumnul complet închis
Figura 8.2: Brațul mecanic cu pumnul complet deschis
#2. Test de viteză: a fost măsurată durata închiderii/deschiderii complete a pumnului: s-a obținut un timp relativ mare, de 3 minute.
#3. Test de rezistență: Testul a fost făcut utilizând o sticlă de plastic ce conținea 1L de apă. Rezultatul testului este ilustrat în figura 8.3.
#4. Test de prins obiecte cu două degete. Acest test a fost dus la bun sfârșit, putând fi ridicate obiecte utilizând doar două degete. Test ilustrat in figura 8.4.
Figura 8.4: Brațul cu degetele în poziție închisă pentru testul de prins cu două degete
Bibliografie
https://en.wikipedia.org/wiki/Powered_exoskeleton
https://en.wikipedia.org/wiki/Human_Universal_Load_Carrier
https://en.wikipedia.org/wiki/Stepper_motor
https://en.wikipedia.org/wiki/Atmel_AVR
https://en.wikipedia.org/wiki/ULN2003A
https://en.wikipedia.org/wiki/Microcontroller
„Design of a Human Hand prosthesis” de Paul Venimiglia
http://ham.elcom.pub.ro/proiect2/doc.htm
Referințe bibliografice utilizate
Referința 1: https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Human_Universal_Load_Carrier.jpg/220px-Human_Universal_Load_Carrier.jpg
Referința 2: https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Stepper_motor.jpg/800px-Stepper_motor.jpg
Referința 3: https://upload.wikimedia.org/wikipedia/commons/7/77/Unipolar-stepper-motor-windings.png
Referința 4: https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Stepper_Motor_11.jpg/800px-Stepper_Motor_11.jpg
Referința 5: https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Drive.png/440px-Drive.png
Referința 6: https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Microcontrollers_Atmega32_Atmega8.jpg/653px-Microcontrollers_Atmega32_Atmega8.jpg
Referința 7: https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/ATmega8_01_Pengo.jpg/800px-ATmega8_01_Pengo.jpg
Referința 8: https://upload.wikimedia.org/wikipedia/commons/a/a2/ULN2003A_Pin_Connection.PNG
Referința 9: „Design of a Human Hand prosthesis” de Paul Venimiglia, pagina 19, figura 14;
Referința 10: https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRjU0d1pvPnKMv-U5RKOML_-7yQhshD3P6q8qlfFX4afwBx0uE2
Referința 11: http://www.conexelectronic.ro/img_gd.php?img_op=0&to_w=100&img_path=upl/product/photo/12139.jpg
Anexe
Anexa 1: Fișierul init.c
/* initialization file */
#include <mega8.h>
#include "defs.h"
/*
* most intialization values are generated using Code Wizard and depend on clock value
*/
void Init_initController(void)
{
// Port B initialization
PORTB=0b11100100; // B.2 needs pull-up resistor
DDRB=0b00011011;
DDRB&=~(1<<PINB.5); // Data direction input for PINB5
DDRB&=~(1<<PINB.6); // Data direction input for PINB6
DDRB&=~(1<<PINB.7); // Data direction input for PINB7
// Port C initialization
PORTC=0x00;
DDRC=0b11111111;
// Port D initialization
PORTD=0b00011100;
DDRD= 0b01000000; // D.6 is LED
DDRD&=~(1<<PIND.2); // Data direction input for PIND2
DDRD&=~(1<<PIND.3); // Data direction input for PIND3
DDRD&=~(1<<PIND.4); // Data direction input for PIND4
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7.200 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0D;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
// 1 sec = 7200 counts = 1C20H counts
// 1C20H = 1CH (MSB) and 20H (LSB)
OCR1AH=0x1C;
OCR1AL=0x20;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
// (Timer 1 Compare Match A Interrupt)
TIMSK=0x10;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x2F;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048
// Write 2 consecutive values to enable watchdog
WDTCR=0x1F;
WDTCR=0x0F;
}
Anexa 2: Fișierul defs.h
/* definitions / defines file */
#define DEFS_H
#define SW_VERSION 21 /* i.e. major.minor software version nbr. */
#ifndef NULL
#define NULL 0
#endif
// data types
#define byte char
#define word unsigned int
#define dword unsigned long
// logix …
#define TRUE 1
#define FALSE 0
#define DUMMY 0
#define TOPTR(x) ((word*)x)
#define TOPTRc(x) ((byte*)x)
#define wdogtrig() #asm("wdr") // call often if Watchdog timer enabled
#ifndef CLK
#define CLK 13500000 // quartz frequency [Hz]
#endif
#define CR 0x0D
#define LF 0x0A
#define LED1 PORTD.6 // PORTx is used for output
#define SW1 PINB.2 // PINx is used for input
#define F1C PIND.2
#define F2C PIND.3 // posibil sa nu fie necesar si sa pot adauga butoanele
#define F3C PIND.4 // direct pe placa fara cod in plus la definitii
#define F1O PINB.5
#define F2O PINB.6
#define F3O PINB.7
//motor coils definitions
//motor 1 (index) coil definitions
#define A1 PORTC.0
#define B1 PORTC.1
#define C1 PORTC.2
#define D1 PORTC.3
//motor 2 (2nd finger) coil definitions
#define A2 PORTC.4
#define B2 PORTC.5
#define C2 PORTC.6
#define D2 PORTC.7
//motor 3 (thumb) coil definitions
#define A3 PORTB.0
#define B3 PORTB.1
#define C3 PORTB.3
#define D3 PORTB.4
#include "funct.h"
Anexa 3: Fișierul funct.h
void Init_initController(void);
Anexa 4: Fișierul main.c
/*********************************************
Project : Kuro Usagi
**********************************************
Chip type : ATmega16
Clock frequency : 7.3728 MHz
*********************************************/
#include <mega8.h>
#include <stdio.h>
#include <delay.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"
//*************************************************************************************************
//*********** BEGIN SERIAL STUFF (interrupt-driven, generated by Code Wizard) *********************
//*************************************************************************************************
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
// USART Receiver buffer
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];
int SW2C=0;
int SW3C=0;
#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif
// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index]=data;
if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
};
};
}
#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
–rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif
// USART Transmitter buffer
#define TX_BUFFER_SIZE 8
char tx_buffer[TX_BUFFER_SIZE];
#if TX_BUFFER_SIZE<256
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#else
unsigned int tx_wr_index,tx_rd_index,tx_counter;
#endif
// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (tx_counter)
{
–tx_counter;
UDR=tx_buffer[tx_rd_index];
if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
};
}
#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
++tx_counter;
}
else
UDR=c;
#asm("sei")
}
#pragma used-
#endif
//*************************************************************************************************
//********************END SERIAL STUFF *********************************************************
//*************************************************************************************************
/*
* Timer 1 Output Compare A is used to blink LED
*/
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
LED1 = ~LED1; // invert LED
}
/*
* main function of program
*/
//motor step functions
void STEPPERCW1()
{
{A1=1;
B1=0;
C1=0;
D1=0;}
delay_ms (2);
{A1=0;
B1=1;
C1=0;
D1=0;}
delay_ms (2);
{A1=0;
B1=0;
C1=1;
D1=0;}
delay_ms (2);
{A1=0;
B1=0;
C1=0;
D1=1;}
delay_ms (2);
}
void STEPPERCCW1()
{
{A1=0;
B1=0;
C1=0;
D1=1;}
delay_ms (2);
{A1=0;
B1=0;
C1=1;
D1=0;}
delay_ms (2);
{A1=0;
B1=1;
C1=0;
D1=0;}
delay_ms (2);
{A1=1;
B1=0;
C1=0;
D1=0;}
delay_ms (2);
}
void STEPPERCW2()
{
{A2=1;
B2=0;
C2=0;
D2=0;}
delay_ms (2);
{A2=0;
B2=1;
C2=0;
D2=0;}
delay_ms (2);
{A2=0;
B2=0;
C2=1;
D2=0;}
delay_ms (2);
{A2=0;
B2=0;
C2=0;
D2=1;}
delay_ms (2);
}
void STEPPERCCW2()
{
{A2=0;
B2=0;
C2=0;
D2=1;}
delay_ms (2);
{A2=0;
B2=0;
C2=1;
D2=0;}
delay_ms (2);
{A2=0;
B2=1;
C2=0;
D2=0;}
delay_ms (2);
{A2=1;
B2=0;
C2=0;
D2=0;}
delay_ms (2);
}
void STEPPERCW3()
{
{A3=1;
B3=0;
C3=0;
D3=0;}
delay_ms (2);
{A3=0;
B3=1;
C3=0;
D3=0;}
delay_ms (2);
{A3=0;
B3=0;
C3=1;
D3=0;}
delay_ms (2);
{A3=0;
B3=0;
C3=0;
D3=1;}
delay_ms (2);
}
void STEPPERCCW3()
{
{A3=0;
B3=0;
C3=0;
D3=1;}
delay_ms (2);
{A3=0;
B3=0;
C3=1;
D3=0;}
delay_ms (2);
{A3=0;
B3=1;
C3=0;
D3=0;}
delay_ms (2);
{A3=1;
B3=0;
C3=0;
D3=0;}
delay_ms (2);
}
// step functions end
void main (void)
{
byte temp;
Init_initController(); // this must be the first "init" action/call!
#asm("sei") // enable interrupts
LED1 = 1;
SW2C=0;
SW3C=0;
// initial state, will be changed by timer 1
//index finger motor initial state
A1=0; // initial state coil A motor 1
B1=0; // initial state coil B motor 1
C1=0; // initial state coil C motor 1
D1=0; // initial state coil D motor 1
//2nd finger motor initial state
A2=0; // initial state coil A motor 2
B2=0; // initial state coil B motor 2
C2=0; // initial state coil C motor 2
D2=0; // initial state coil D motor 2
//thumb motor initial state
A3=0; // initial state coil A motor 3
B3=0; // initial state coil B motor 3
C3=0; // initial state coil C motor 3
D3=0; // initial state coil D motor 3
// stepcounter=1;
while(1)
{
wdogtrig(); // call often else processor will reset
//new code for motors
if (F1C==0)
{ delay_ms(10);
if (F1C==0)
{
while (F1C==0)
{
STEPPERCCW1();
}
}
}
else
if (F1O==0)
{ delay_ms(10);
if (F1O==0)
{
while (F1O==0)
{
STEPPERCW1();
}
}
}
if (F2C==0)
{ delay_ms(10);
if (F2C==0)
{
while (F2C==0)
{
STEPPERCCW2();
}
}
}
else
if (F2O==0)
{ delay_ms(10);
if (F2O==0)
{
while (F2O==0)
{
STEPPERCW2();
}
}
}
if (F3C==0)
{ delay_ms(10);
if (F3C==0)
{
while (F3C==0)
{
STEPPERCCW3();
}
}
}
else
if (F3O==0)
{ delay_ms(30);
if (F3O==0)
{
while (F3O==0)
{
STEPPERCW3();
}
}
}
if ((F1O==0)&&(F2O==0))
{ delay_ms(10);
if ((F1O==0)&&(F2O==0))
{
while ((F1O==0)&&(F2O==0))
{
STEPPERCW1();
STEPPERCW2();
}
}
}
if ((F1O==0)&&(F3O==0))
{ delay_ms(10);
if ((F1O==0)&&(F3O==0))
{
while ((F1O==0)&&(F3O==0))
{
STEPPERCW1();
STEPPERCW3();
}
}
}
if ((F3O==0)&&(F2O==0))
{ delay_ms(10);
if ((F3O==0)&&(F2O==0))
{
while ((F3O==0)&&(F2O==0))
{
STEPPERCW3();
STEPPERCW2();
}
}
}
if ((F1C==0)&&(F2C==0))
{ delay_ms(10);
if ((F1C==0)&&(F2C==0))
{
while ((F1C==0)&&(F2C==0))
{
STEPPERCCW1();
STEPPERCCW2();
}
}
}
if ((F1C==0)&&(F3C==0))
{ delay_ms(10);
if ((F1C==0)&&(F3C==0))
{
while ((F1C==0)&&(F3C==0))
{
STEPPERCCW1();
STEPPERCCW3();
}
}
}
if ((F3C==0)&&(F2C==0))
{ delay_ms(10);
if ((F3C==0)&&(F2C==0))
{
while ((F3C==0)&&(F2C==0))
{
STEPPERCCW3();
STEPPERCCW2();
}
}
}
if ((F1C==0)&&(F2O==0))
{ delay_ms(10);
if ((F1C==0)&&(F2O==0))
{
while ((F1C==0)&&(F2O==0))
{
STEPPERCCW1();
STEPPERCW2();
}
}
}
if ((F1C==0)&&(F3O==0))
{ delay_ms(10);
if ((F1C==0)&&(F3O==0))
{
while ((F1C==0)&&(F3O==0))
{
STEPPERCCW1();
STEPPERCW3();
}
}
}
if ((F2C==0)&&(F3O==0))
{ delay_ms(10);
if ((F2C==0)&&(F3O==0))
{
while ((F2C==0)&&(F3O==0))
{
STEPPERCCW2();
STEPPERCW3();
}
}
}
if ((F1O==0)&&(F2C==0))
{ delay_ms(10);
if ((F1O==0)&&(F2C==0))
{
while ((F1O==0)&&(F2C==0))
{
STEPPERCW1();
STEPPERCCW2();
}
}
}
if ((F1O==0)&&(F3C==0))
{ delay_ms(10);
if ((F1O==0)&&(F3C==0))
{
while ((F1O==0)&&(F3C==0))
{
STEPPERCW1();
STEPPERCCW3();
}
}
}
if ((F2O==0)&&(F3C==0))
{ delay_ms(10);
if ((F2O==0)&&(F3C==0))
{
while ((F2O==0)&&(F3C==0))
{
STEPPERCW2();
STEPPERCCW3();
}
}
}
if ((F1O==1)&&(F1C==1))
{ delay_ms(10);
if ((F1O==1)&&(F1C==1))
{
while ((F1O==1)&&(F1C==1))
{
//return to initial states so the fingers don't move
A1=0; // initial state coil A motor 1
B1=0; // initial state coil B motor 1
C1=0; // initial state coil C motor 1
D1=0; // initial state coil D motor 1
}
}
}
if ((F2O==1)&&(F2C==1))
{ delay_ms(10);
if ((F2O==1)&&(F2C==1))
{
while ((F2O==1)&&(F2C==1))
{
//return to initial states so the fingers don't move
A2=0; // initial state coil A motor 1
B2=0; // initial state coil B motor 1
C2=0; // initial state coil C motor 1
D2=0; // initial state coil D motor 1
}
}
}
if ((F3O==1)&&(F3C==1))
{ delay_ms(10);
if ((F3O==1)&&(F3C==1))
{
while ((F3O==1)&&(F3C==1))
{
//return to initial states so the fingers don't move
A3=0; // initial state coil A motor 1
B3=0; // initial state coil B motor 1
C3=0; // initial state coil C motor 1
D3=0; // initial state coil D motor 1
}
}
}
//motor code end
if(rx_counter) // if a character is available on serial port
{
temp = getchar();
if(temp == '?')
printf("\r\nSwVersion:%u.%u\r\n", SW_VERSION/10, SW_VERSION%10);
else
putchar(temp+1); // echo back the character + 1 ("a" becomes "b", etc)
}
if(SW1 == 0) // pressed
{
delay_ms(30); // debounce switch
if(SW1 == 0) // alternate before values and values/4 for OCR1A register
{ // so LED will blink slow or fast
while(SW1==0)
wdogtrig(); // wait for release
if(OCR1AH == 0x1C)
{TCNT1 = 0; OCR1AH = 0x07; OCR1AL = 0x08;}
else
{TCNT1 = 0; OCR1AH = 0x1C; OCR1AL = 0x20;}
}
}
}// end main loop
}
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: Brat Robotic, Comandat Electronic (ID: 162012)
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.
