Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pitanja u vezi tutorijala | Programiranje PIC mikrokontrolera u jeziku C
#21

Hvala na komplimentima Wink

Zamolio bih samo da pišete pune oznake PIC-eva a ne skraćene.

Iskusniji tačno znaju našta se misli kada se napiše npr 887 ali početnicima je to jako zbunjujuće.

Dakle u pitanju je skraćena oznaka od modela PIC16F887.

Predpostavljam da će mo se u ovom tutorijalu najviše vrteti oko modela iz PIC16F i PIC18F serije i iz tog razloga da nebi bilo zabune valja pisati pune oznake.

Reply
#22
<p>Da pomognem malo Mikiju sa nekim korisnim detaljima.</p>
<p>&nbsp;</p>
<p>Možda bi za početnike bilo dobro da krenu odmah od PIC18F modela...</p>
<p>&nbsp;</p>
<p>Nema arbitracije sa memorijskim bankama (linearno adresiranje), PLL&nbsp; za&nbsp; &gt;=40MHz oscilatora.</p>
<p>&nbsp;</p>
<p>Sve je isto kao kod starog PIC16F877 osim brzine i prilično dosadne i ponekad nezgodne arbitracije memorijskim bankama.</p>
<p>&nbsp;</p>
<p>Jedan od najjednostavnijih, kod koga se hardver poklapa sa PIC16F877 i/p&nbsp; je PIC18F452 i/p.</p>
<p>&nbsp;</p>
<p>Pinovi su potpuno kompatibilni.</p>
<p>&nbsp;</p>
<p>U njega se mogu bukvalno preneti sa beznačajnim izmenama svi programi pisani za PIC16F877, za koga postoji gomila besplatnih tutorijala i primera.</p>
<p>&nbsp;</p>
<p>Ovo je samo predlog za one koji bi praćenjem nekog primera za PIC16F877 još lakše to radili sa PIC18F452 jer je mlađi i napredniji model, a kompatibilan.</p>
<p>&nbsp;</p>
<p>Oba su prilično stari modeli, ali zato jednostavni i sa dovoljno mogućnosti za vrlo ozbiljne naprave.</p>
<p>&nbsp;</p>
<p>Sa bilo kojim od njih se može napraviti PLC sa 25in/out (bez ekspandera)&nbsp; +&nbsp; tastatura&nbsp; +&nbsp; LCD&nbsp; +&nbsp; RS232 komunikacija za online upisivanje bootloaderom, čim se može upravljati prilično složena mašina.</p>
<p>&nbsp;</p>
<p>Za početak ne treba birati model sa mnogo specijalnih modula unutra, jer početniku je uvek najteže da raskrsti sa setovanjem tih modula. Za upoznavanje SFR registara je potrebno vreme.</p>
<p>&nbsp;</p>
<p>Kod PIC18F452 je dovoljno u funkciji inicijalizacije (konfiguracije) MCU samo napisati instrukciju</p>
<p>&nbsp;</p>
<p>ADCON1 = 0x07;&nbsp; /* adc off */</p>
<p>&nbsp;</p>
<p>i svi će pinovi postati digitalni, što je početniku i najpotrebnije.</p>
<p>&nbsp;</p>
<p>Ako to ne uradite, taj MCU je inicijalno postavljen sa uključenim A/D konvertorima na ANx pinovima, što je za početnika prerano i napraviće mu zbrku.</p>
<p>&nbsp;</p>
<p>Posle toga se lako mogu obavljati razni blink testovi i slično.</p>
<p>&nbsp;</p>
<p>Vlo mladi modeli imaju gomilu modula unutra i zahtevaju vremena i posla za njihovo pravilno setovanje.</p>
<p>To vam je kao kod novijih mobilnih telefona: bezbroj mogućnosti a treba vam samo nekoliko :-).</p>
<p>Lakše je zato početi od jednostavnijih.</p>
<p>-------------------------------------</p>
<p>Kod većine PIC kontrolera korisnički pinovi mogu biti ulazni ili izlazni, po izboru.</p>
<p>&nbsp;</p>
<p>Kada se konfigurišu kao ulazni, onda imaju vrlo visoku ulaznu impendansu, jednaku uobičajenim logičkim kolima iz CMOS serije (serija 40xx ili 45xx).</p>
<p>&nbsp;</p>
<p>Za razliku od CMOS kapija, kada se na PIC pinovi koriste kao izlazni, mogu raditi sa +-25 mA po pinu, a u datasheet-u treba pogledati koliko ih odjednom sme davati toliko struje.</p>
<p>&nbsp;</p>
<p>+25mA znači da svaki pin kao izlazni može davati potrošaču 25mA iz +5V napajanja(+Vdd), gde je drugi kraj potrošača na masi(-Vss). To je praktično aktiviranje potrošača stanjem 1 na dotičnom pinu.</p>
<p>&nbsp;</p>
<p>-25mA pak znači da isti taj pin može pokretati potrošač čiji je jedan kraj "okačen" na +5V(+Vdd), a pin ga aktivira stanjem 0, tj. "povuče ga ka masi.</p>
<p>&nbsp;</p>
<p>Ne mogu svi pinovi odjednom imati po 25mA zbog ograničenja discipacije MCU.</p>
<p>&nbsp;</p>
<p>Kod npr. PIC18F452 piše:</p>
<p>&nbsp;</p>
<p>Maximum current out of VSSpin ...........................................................................................................................300 mA<br>
Maximum current into VDDpin .............................................................................................................................. 250 mA</p>
<p>&nbsp;</p>
<p>To pokazuje koliko bi pinova smelo istovremeno biti opterećeno maksimalnom strujom.</p>
<p>&nbsp;</p>
<p>Ako nam je potrebno baš dosta izlaznih pinova koji bi trebalo da daju dosta struje za svoje potrošače, onda možemo primeniti "caku" da 10 pinova koristimo sa stanjem 1 kao aktivnim snabdevanjem potrošača, i istovremeno još 11 sa invertovanom logikom, tj. sa stanjem 0 kao aktivnim snabdevanjem potrošača (povuku ih ka masi).</p>
<p>Tako nećemo "overiti" na primer PIC o kome sam pisao.</p>
<p>&nbsp;</p>
<p>Takođe mnogi početnici pogreše tako što pin RA4 upotrebe kao izlaz sa aktivnim 1. Taj pin je skoro po pravilu kod većine PIC open drain, tj. ima mosfet samo ka masi. Ako se koristi kao snažniji izlaz, onda mora "povući" potrošač ka masi, ili ako je potrošač slabašan onda mora imati pull-up otpornik koji će taj potrošač snabdevati stanjem 1.</p>
<p>&nbsp;</p>
<p>Daleko je jednostavnije da se odmah naviknete da taj pin koristite uvek kao ulaz (ukoliko nužda ne zahteva drugačije).</p>
<p>&nbsp;</p>
<p>------------------------------------</p>
<p>Nekorišćene pinove kod bilo kog MCU ne treba ostaviti da "lebde". Ako postoje pinovi koji lebde mogu se događati vrlo neočekivane pojave. Oni pinovi koji su konfigurisani kao ulazi, vrlo su visokoimpendansni, pa samo približavanje ruke do njih ih može pobuditi sa mrežnim brumom od 50Hz, koji potiče sa vašeg tela, a zbog blizine mrežnih provodnika pored vas, a vrlo neočekivanim rezultatima rada :-).</p>
<p>&nbsp;</p>
<p>Ne treba ostavljati lebdeće pinove čak ni kada radite sa baterijama, na stolu postavljenom na livadi, jer i tada svojim kapacitativnim punjenjem (od trenja odeće), približavanjem i udaljavanjem od PIC možete menjati stanje na lebdećim ulazima.</p>
<p>&nbsp;</p>
<p>Važno pravilo broj 1 za početnike:</p>
<p>-nikada ne ostavljajte neupotrebljene pinove lebdećim!</p>
<p>Ili ih konfigurišite kao izlaz (i ako vam nisu potrebni), ili im stavite pull-up ili pull-down otpornike reda nekoliko do nekoliko desetina&nbsp; K, ka +Vdd ili -Vss, respektivno.</p>
<p>&nbsp;</p>
<p>Pravilo broj 2 za početnike:</p>
<p>-svakom korisničkom pinu, odmah do čipa, povežite serijski otpornik od bar 220R najmanje. Kada greškom konfigurišete pin kao izlaz, a na njemu je npr. taster ka masi ili ka Vdd, nećete spaliti MCU (mada se PIC baš teško spaljuju, ali ipak može :-). Taj otpornik će imati ulogu ograničenja struje na max. oko 22mA ma šta vi uradili sa tim pinom, a kada pin koristite kao ulaz ni malo neće smetati, jer je impendansa ulaza toliko visoka da taj otpornik biva "nevidljiv".</p>
<p>Impendansa pina kao ulaza je &gt;5Megaohm, tj. u najgorem temperaturnom uslovu mu je potrebno max, 1uA, što će na tom serijskom otporu od 220R izazvati pad napona (umanjenje veličine ulaznog signala) za 220uV, što je potpuno beznačajna veličina, Dakle. sa aspekta ulaza taj otpornik ne postoji, a u slučaju naše greške zaštitiće pin.</p>
<p>&nbsp;</p>
<p>Ja na primer tu stavljam od 330-680R, jer to je dovoljno za pogon većine LED ili optokaplerskih LED. Ne razmišljam da li će mi potrošač biti u kratkom spoju ili da li ću slučajno "nabosti" pin ka masi ili plusu...</p>
<p>&nbsp;</p>
<p>Eto nekih korisnih info uglavnom vezanih za hardver.</p>
<p>&nbsp;</p>
<p>Kada bude vremena dodaću još po nešto korisno.</p>
Reply
#23
<p>Dok sam još pri koncentraciji:</p>
<p>&nbsp;</p>
<p>Konfiguracija pina kao ulaznog ili izlaznog pina je ekstremno brza pojava. To je jedna jedina instrukcija i kod PIC koji radi na primer sa 40MHz ta instrukcija traje 100nS (f_osc/4).</p>
<p>&nbsp;</p>
<p>Dakle, možemo munjeviti menjati orijentaciju pina kao ulaznog ili izlaznog, istovremeno mu menjajući impendansu iz ekstremno visoke do vrlo niske.</p>
<p>&nbsp;</p>
<p>To se na primer može veoma zgodno iskoristiti na jednostavan način kao sa sličice:</p>
<p>&nbsp;</p>
<p>[attachment=7406:pot.pdf]</p>
<p>&nbsp;</p>
<p>Kada smo npr. iskoristili sve A/D konvertore, na ovaj način možemo saznati položaj nekog potenciometra, tako što na kratko konfigurišemo pin kao izlaz, kratkim impulsom napunimo C kroz 220R, potom odmah promenimo pin kao ulaz i merimo vreme do njegovog stizanja u nisko stanje (pražnjenje C kroz pot.).</p>
<p>&nbsp;</p>
<p>To je jedan od primera.</p>
<p>&nbsp;</p>
<p>ili možemo istim pinom kontrolisati dve LED (na primer različite boje) kao sa sličice:</p>
<p>&nbsp;</p>
<p>[attachment=7407:2led.pdf]</p>
<p>&nbsp;</p>
<p>Kada je pin ulaz, neće svetleti ni jedna, kada je izlaz stanje 1 aktivira jednu led, a stanje 0 drugu.</p>
<p>&nbsp;</p>
<p>To može biti veoma korisno kod PIC sa malo pinova.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>


Attached Files
.pdf   pot.pdf (Size: 3,73 KB / Downloads: 23)
.pdf   2led.pdf (Size: 6,83 KB / Downloads: 27)
Reply
#24
<p>Društvo, usputno vas pratim, pošto imam puno obaveza ovih dana, samo želim da pohvalim Mikijevu inicijativu i zaista lep i "skockan" tutorial. Za sada ništa nebih dodavao ni oduzimao Smile</p>
<p>Macoline postove takođe, ako u ovom trenutku ne možete da pratite (imate nedovoljno iskustva) obavezno ih negde izdvojite, "zlata" su vredni, pa kada bude došlo vreme biće itekako korisni.</p>
<p>&nbsp;</p>
<p>Još bih samo napomenuo i ovo, rednim otpornikom ka svakom pinu smanjujete mogućnost da glič iz spoljnog okruženja "zaključa" pin, odnosno "latchup"-je isti prevelikom energijom. Većina pinova konkretno kod PIC mikrokontrolera ima klamp diode ka +Vdd i Vss, i struja koju one mogu da podnesu je reda veličine 1mA (kod starijih generacija) do čitavih 20mA kod novijih mikrokontrolera. Rednim otpornicima ukoliko se ograniči ova struja, pin mikrokontrolera postaje mogu slobodno reći neuništiv. Primer za to je da sam u nekim mojim projektima koristio 1M na pin mikrokontrolera i direktno dovodio 220V AC na taj pin. Nakon 7 godina (24h/365dana) rada taj uređaj i dalje radi kako treba Smile</p>
<p>&nbsp;</p>
<p>Moja opaska oko konfiguratora, ako neko želi da zaista nauči rad sa mikrokontrolerima, mora se detaljno upoznati sa njegovim registrima i periferijama, opciono asembler istog, tako da je "medveđa" usluga ići odmah na konfigurator. Njega bih pre savetovao iskusnijima, da bi ubrzali proces podešavanja....</p>
<p>&nbsp;</p>
<p>Samo napred....</p>
Reply
#25
<p>Moje pitanje skoro da nema veze sa tutorijalom, ali je ipak pitanje ( to se trazi u naslovu teme ).</p>
<p>U jednoj primeni potrebno je da izlazni pin ide direktno &nbsp;na ulazni pin ( koji prati pojavu prednje ivice sa izlaznog pina).</p>
<p>Kako optimalno povezati ova 2 pina?</p>
Reko sam ti sve. a pomenuo te ne. ipak sada znaju svi. da si to ti
Reply
#26
<p>Aj i ja da dodam nesto sto mi je dosta znacilo kad sam pocinjao (sto i nije bilo tako davno) Smile</p>
<p>1. Procitati Datasheet za kontroler kojim zelite da se pozabavite (obavezno)</p>
<p>2. Ako imate mogucnosti uvek koristiti interne pull-up/down otpornike</p>
<p>3. Ako kacite potrosace koji vuku struju priblizno maksimlanoj struji koju pin moze da da , uvek kada imate prilike neka pin "upija" struju jer se tako manje greje kontroler. (Znaci da se potrosac pali kada je pin na niskom logickom nivou 0V)</p>
<p>4. Koristiti za pocetak kontrolere koji su u DIPxx jer su mnogo laksi za koriscenje od za kontrolere u SMD .</p>
<p>5. Mozda ce vas obeshrabriti programiranje u Asembleru ali po meni je to, ako ozbiljnije hocete da se pozabavite programiranjem, neophodno znati , mada za pocetak i C ili Basic (i Pascal je veoma dobar mada se meni licno ne svidja) ce raditi posao ...</p>
Reply
#27
<blockquote class="ipsBlockquote" data-author="Milan95" data-cid="21338" data-time="1393151196">
<div>
<p>2. Ako imate mogucnosti uvek koristiti interne pull-up/down otpornike</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>Ne nužno bolje. Interni pull-up/down su jako slabi, ekvivalent otporniku od 100-ak k, što u "šumovitom" okruženju može biti jako problematično. Ako je primena uređaja u energetskom ambijentu, ipak koristite eksterne otpornike manjih vrednosti, moja praksa je 1k.</p>
<p>&nbsp;</p>
<blockquote class="ipsBlockquote" data-author="Milan95" data-cid="21338" data-time="1393151196">
<div>
<p>5. Mozda ce vas obeshrabriti programiranje u Asembleru ali po meni je to, ako ozbiljnije hocete da se pozabavite programiranjem, neophodno znati , mada za pocetak i C ili Basic (i Pascal je veoma dobar mada se meni licno ne svidja) ce raditi posao ...</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>I ovo je tema o kojoj možemo konstruktivno da polemišemo Smile Apsolutno se slažem da je neophodno da se korisnik upozna sa arhitekturom mikrokontrolera i ograničenjima iste, što se jako lepo sagledava kroz asembler, međutim da bi korisnik programirao u asembleru potrebno je puno iskustva i pažnje. Portabilnost kodova je jako diskutabilna ili bolje reći problematična, ne samo između različitih proizvođača mikrokontrolera već i generacijski različitih istog proizvođača.</p>
<p>&nbsp;</p>
<p>Jednom prilikom je rađena analiza optimizacije koda koju generiše čovek programer u assembleru i dobrog kompajlera koji prevodi C kod iste funkcije. Analiza je pokazala da su kompajleri (napominjem, dobri kompajleri) u mogućnosti da u 90% aplikacija pokažu superiornost u odnosu na prosečnog programera. Tako da danas nema dileme, viši programski jezici su preporuka za korišćenje.</p>
<p>&nbsp;</p>
<p>Neko moje iskustvo sa ljudima kojima sam pomagao da krenu sa mikrokontrolerima je da se od asemblera prilično obeshrabre, tako da pažljivo sa tim....</p>
<p>&nbsp;</p>
<p>P.S. Ko želi da pročita jako dobre tekstove i šta znači optimizacija koda, hardvera i pristup projektovanju mikrokontrolerskih uredjaj, obavezno štivo su članci Voje Antonića (PC Press devedesetih godina) koji je impresionirao i sam Microchip. Oni su mu poklonili gomilu razvojnih alata itd... Inače Voja Antonić je projektovao, izradio i pisao OS za računar Galaksija davne 1983. godine. Kasnije je radio sa Intel 8031, 8051 i PIC mikrokontrolerima.</p>
<p>Evo njegovog najpoznatijeg uređaja sa izvornim kodom na asembleru, a uređaj je baziran na PIC16F84 mikrokontroleru Smile</p>
<p><a data-ipb='nomediaparse' href='http://ww1.microchip.com/downloads/en/AppNotes/00689a.pdf'>http://ww1.microchip.com/downloads/en/AppNotes/00689a.pdf</a></p>
Reply
#28

Moram i ja da dam nekoliko komentara Smile

Možda nemam toliko iskustva sa PIC-evima kao npr npejcic ili Macola kojima je to trenutno sastavni deo profesije ali imam jako dug staž u radu sa njima, bukvalno od kad su se pojavili (da baš to iz vremena Voje Antonića) Smile

U periodu kada sam i ja to profesionalno radio, isprojektovao sam par stotina različitih apikacija. Sad sam u nekim drugim vodama i to mi je ostao samo hobi.

Ono što želim da kažem je vezano za Assembler i neke druge višlje programske jezike poput C.

Razvojni alati (IDE i kompajleri) su tokom vremena veoma veoma napredovali. Ne samo sto su ti alati napredovali nego su oni posledično pratili trend koji su noviji mikrokontroleri diktirali.

Pod ovim najviše mislim na to da su sadašnja procesorksa jezgra skoro potpuno optimizovana za pisanje programa u jeziku C!

To praktično znači da je skoro isto (recimo 90% isto) po pitanju zauzeća momorije i brzine izvršavanja programa pisali program u vrlo kompleksnom Assembleru ili pisali program u C.

Prevodilac za C jezik će u većini slučajeva za neku funkciju napraviti ekvivalento isti mašinski code kao da smo to pisali u Assembler-u i to pod predpostavkom da skoro aposlutno poznajemo tu problematiku i da znamo sve best-practice i cake kako se najoptimalnije neka tražena funkcija logički realizuje.

Assembler je nekada bio must-have izbor jer su mikrokontroleri bili sa skromnim brzinama i memoriskim resursima.

Sada kada memorija i brzina više nije toliki problem kao pre, pisanje programa u C je potpuno prihvatljivo ne samo za početnike već i za surove profesionalce.

A i kada nam ponestane resursa, šta je problem uzeti neki bolji PIC, pa sad ih prave sa po 1-2MB flash memorije i 200+MIPS i ne znam šta da pišete to ne može da se potroši Smile

Takođe, jezik C je sad praktično standard za sva moguća programiranja i pisanja aplikacija za razne platforme, ne samo za PIC već za gomilu drugih mikrokontrolera, PC i desktop aplikacija i sl.

Dodatno C jezik je sad vrlo vrlo sličan nekim popularnim (WEB) jezicima poput JavaScript ili PHP pa onima koji su možda malo više u tim vodama pisanje programa u C će biti opuštencija Smile

Zato sam u onom tutorijali prvenstveno se bazirao na jeziku C jer u ovom trenutku ja lično smatram da Assembler nije neophodan za poznavanje, bar ne detaljno.

Ono što je specifično za svaki mikrokontroler su njegovi registri za kontrolu periferija u drugih internih funkcija i to treba da se poznaje nevezano za to u kojem jeziku pišemo program.

Opet ovde dolazi u prednost moderan IDE jer nas može vrlo jednostavno "posavetovati" kada krenemo da pišemo neku naredbu, dovoljno je recimo ukucati POR i zatim pritisnuti CTRL+Space i na ekranu će izaci spisak svih raspolozivih funkcija i opcija koje počinju tim slovima (code complete, npr PORTA). To je fenomenalna opcija a sećam se kako je to nekad bilo kada su se programi pisali u običnim tekstualnim editorima, muka živa.

To je samo jedan primer ekstra korisne funkcije a spomenuti Mplab X ih ima tonu sličnih Smile

Reply
#29
<p>Pošto je ovo zanimljivo mesto za svakakve predloge i pomoc pocetnicima i onima koji su donekle stigli u programerskom poslu, evo jednog priloga iz realnog sveta kontrole industrijskih mašina.<br><br>
Pominjao sam&nbsp; PIC16F877, kao model za koga postoji bezbroj aplikacija i gotovih rešenja na net-u.<br><br>
Kao njegovog mladeg naslednika sa nekoliko poboljšanja PIC18F452, gde su kodovi za PIC16F877 vrlo portabilni sa beznacajnim izmenama.<br><br>
I sada pominjem PIC18F4620, pin kompatibilnog, sasvim slicnog sa prethodna dva, osim što ima neuporedivo veci kapacitet svih memorija (fleš,ram,eeprom) i par dodatnih modula.<br><br>
Takode se u njega mogu portovati kodovi za 877 i 452,&nbsp; a da bi svi korisnicki pinovi bili digitalni (pomoc pocetnicima) u inicijalizaciji treba iskljuciti A/D konvertore i oba komparatora.<br><br>
Ovako:<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ADCON1 = 0b00001111;&nbsp; /* adc off */&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //4620<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CMCON&nbsp; = 0b00000111;&nbsp; /* comparators off */&nbsp; //4620<br><br>
Prica o ovim osmobitnim MCU je ovde da bi pocetnicima pokazala da nema potrebe bez razloga se odmah na pocetku hvatati za MCU sa preteranim resursima unutra.<br><br>
Sa bilo kojim od tri prethodno nabrojana MCU, mogu se napraviti stvarno mocni PLC.<br><br>
Primera radi, najsnažniji PLC koji sam napravio sa jednim ortakom, sa PIC16F877 ima 128 in/out, gde je napravljeno nekoliko in/out expandera sa Altera PLD.<br><br>
Jedan malo manji od tog, takode sa PIC16F877, sa 80 in/out, upravlja jednu mašinu za brizganje plastike, kapaciteta 2Kg plastike i 800 Tona sile zatvaranja alata, u Ugrinovcima, blizu našeg forumaša HMAP.<br><br>
Mašina je istocno nemacko-ruska, sa 39 hidraulicnih ventila i 40 senzora.<br><br>
Ogromne špulne na ventilima (ruska posla) 24V 4,5A svaki.<br><br>
U nekim fazama procesa, kroz moj PLC prolazi preko 70A&nbsp; struje pri 24V!!!&nbsp; Tim se može komotno zavarivati nešto...<br><br>
No, uz malo pažnje pri rutovanju vodova, brižljivo izvedenog hardvera, sve to super funkcioniše godinama. Mrzim releje i nikada ih ne stavljam u neku mašinu, pa sve te ventilčine pokrecem low-Rds mosfetima.<br><br>
---------------------------------------------------------------<br><br>
Evo jednog primera sa PIC18F452, gde se istim MCU upravljaju tri mašine odjednom.<br><br>
Prica je takva da je iskorišcen VIŠAK resursa na MCU PIC18f452 (da se ne baci :-) i udružene su tri mašine pod jedno upravljanje.<br><br>
Elem, na početku je nasleđen jedan sučeoni aparat za termootporno zavarivanje (punktovanje), sa višestepenim prekidačem za kontrolu snage i kontaktorima za kontrolu vremena zavarivanja.<br><br>
Ono što je kritično važno u oblasti termootpornog zavarivanja (punktovanja), osim poznatog materijala i komada, su tri parametra: jačina struje, vreme, i pritisak delova međusobno.<br><br>
Da bi zavar bio perfektno ponovljiv, neophodno je da ova tri parametra budu perfektno ponovljivi.<br><br>
Naravno, odmah sam izbacio kontaktore, i trafou od 15KVA napravio tiristorsku kontrolu snage, faznim zasekom pomocu ultra pouzdanog TCA785. Kontrolu vremena sam izveo plasiranjem celobrojnih iznosa mrežnih perioda radi sprečavanja DC bias trafoa, ujedno precizne vremenske kontrole. Kontrolu pritiska pneumatskim cilindrima, sa preciznim regulatorom pritiska ispred...<br><br>
Ono što je trebalo da se proizvodi, gde bi taj aparat bio jedan u lancu operacija, je neki žicani okvir, koji je prethodno trebalo saviti poluautomatom za savijanje žice, potom suceono zapunktovati, pa onda zapunktovati ga u više tacaka za konacni proizvod drugim punkt aparatom, nalik punkt kleštima.<br><br>
Pošto tri prethodno nabrojana PIC "prirodno" obezbeduju 25 in/out, preticala je velika kolicina neupotrebljenih resursa kod kontrole samo suceonog aparata.<br><br>
Naravno, odmah sam predložio da sve tri mašine koje su vezane datim procesom, stavim pod zajedničko upravljanje, i iskoristim isti trafo od sučeonog aparata za drugo punktovanje.<br><br>
Tim bi sve bilo blizu i u lancu proizvodnje, istovremeno ušteđena čitava jedna punkt mašina, uz samo dodavanje još jednog pneumatskog cilindra visokostrujnih kablova i para elektroda za taj treći proces.<br><br>
Predlog je prihvacen.<br><br>
Pošto sve tri mašine mogu potpuno asinhrono raditi svoje poluautomatske procese, neophodno je bilo koristiti neki brzi multitasking, koji bi za korisnika izgledao kao rad u realnom vremenu.<br><br>
Odmah da se ogradim:<br><br>
Ja nisam školovan programer. Kada se prvi kucni racunar pojavio imao sam 16 godina i za mene je tada bio ekonomski nedostižna naprava,<br><br>
Programiranje sam naucio uz put, uglavnom sam, uz povremenu pomoc jednog mog ortaka Mladena, onda Mikijevog sjajnog oca, pocivšeg Zorana Markovica (YU1ZM), i još par drugara koji su se vec bavili tim, pre otprilike 16 godina.<br><br>
Tada je prilicno snažan PIC (generacija sa 16F84) bio neki PIC16F72, sa prozorcetom za brisanje pomocu UV lampe :-).<br><br>
He he, tada je se stvarno moralo voditi racuna o bagovima u kodu, jer svako ponovno programiranje je koštalo 15 minuta brisanja UV lampom :-).<br><br>
Tada je se pisalo u asembleru, normalno :-).<br><br>
Asembler je stvarno naporan za pisanje, ali se njegovim korišcenjem dobiju par nezamenljivih koristi:<br><br>
-prvo, nauci se da se u glavi drži par stotina stavki pod cvrstom konrolom,<br><br>
-drugo, lako je provaliti bag koji eventualno napravi sam kompajler, posmatranjem koda kog je izgenerisao.<br><br>
Da se vratim na pricu. Pocetke sam naucio od tih ljudi, posle (što je vrlo svojstveno za mene) razvijao neke sopstvene metode.<br>
&nbsp;</p>
<p>Mnogim školovanim programerima se ova moja metoda multitaskinga neće svideti, ali ona neoprostivo dobro i pouzdano radi i čitava povorka od sedam taskova se vrti sa par desetina KHz, a može i brže jer sam žrtvovao pola od tog vremena za softversko filtriranje tastera "escape".</p>
<p>&nbsp;</p>
<p>To isto pisano u asembleru je brže samo oko 15%.</p>
<p>&nbsp;</p>
<p>Dakle. uzmite u obzir da nisam školovan programer, već samouk, ali prilično efikasan.</p>
<p>Takođe da zbog ranijeg pisanja u asm volim da koristim globalne varijable.</p>
<p>&nbsp;</p>
<p>Nisam imao vremena za optimizaciju koda. Sve sam napisao ad-hok, na licu mesta.</p>
<p>&nbsp;</p>
<p>Od ključne važnosti mi je bila brzina prolaska kroz sve taskove, tako da ni u kom slučaju ne propustim ni jedan input signal.</p>
<p>&nbsp;</p>
<p>MCU radi sa clk od 40MHz (HSPLL), a vreme jedne instrukcije je 100nS (f_clk/4).</p>
<p>&nbsp;</p>
<p>Samo sam sada prilegao da napišem komentare za ovu priliku, bukvalno od linije do linije, jer to je ono što je najkorisnije početnicima (a sve nas mrzi da ih pišemo, i uvek se posle par godina gorko pokajemo što smo bili lenji :-).</p>
<p>&nbsp;</p>
<p>Za stroge početnike u C jeziku, komentari su:</p>
<p>&nbsp;</p>
<p>//jednolinijski komentar, važi do kraja dotične linije</p>
<p>&nbsp;</p>
<p>/*&nbsp; višelinijski komentar,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; važi od znaka do znaka&nbsp;&nbsp; */</p>
<p>&nbsp;</p>
<p>Radi se samo o dve funkcije: funkcije main i funkcije automatskog rada.</p>
<p>Biće dovoljno za razumevanje poente, nekima odmah, nekima kad dođe vreme...</p>
<pre class="_prettyXprint">
/*-----------------------------------------------------------------------------------------------------*/

void autom_rad(void) //funkcija automatskog ili poluautomatskog rada masine
{
err_no=nema_err; l_err_no=nema_err; //ponisti sve greske kod ulaska
lcd_clear(); //ocisti displej
if(op_status==poluautom){ //ako je poluautom. rad u pitanju
lcd_puts("POLUAUTOM."); //prikazi tekst
}
if(op_status==autom){ //ako je autom. rad u pitanju
lcd_puts("AUTOMATSKI"); //prikazi tekst
}
if(broj_grupa&gt;1){ //ako postoji vise grupa parametara za set razlicitih proizvoda, prikazi indeks proizvoda
lcd_puts(" Pr"); //prikazi tekst
lcd_goto(13); //i broj indeksa proizvoda, pocev od 13. karaktera LCD
lcd_number(ofset_grupe+1,2,3,0); //varijabla, broj decimala, mesto zapete, prisustvo predznaka.
}
semafor_red=0; semafor_green=0; semafor_yelow=0; //pogasi trobojni semafor

clr_line2(); // oslobodi liniju 2 displeja za eventualni brojac komada

/* ovde, ako treba, staviti potrebne preduslove za autom/poluautom rad */
var_busy_flag=0; //!!! obavezno, da bi ponovo radila klesta i suceoni po izlasku iz greske

suc_seq_no=0; kl_seq_no=0; sav_seq_no=0; TRseq_no=0; //svi taskovi u stop stanje, bitno kod povratka iz greske
ped_suc_seq_no=0; ped_kl_seq_no=0; tast_sav_seq_no=0;//svi taskovi u stop stanje, bitno kod povratka iz greske

/*---------------------petlja autom/poluautom rada--------------------*/
while(((op_status==poluautom)||(op_status==autom))&amp;&amp;(!auto_escape)){ //uslovi odrzanja while petlje


//task_ticker^=1; //pin za testiranje vremena prolaza svih taskova, dok se ne zavrsi pisanje programa


if(esc_test())err_no=err_ciklus; //prekinut polu/autom. rad tasterom escape, fatal err.
if(not_aus)err_no=err_n_aus; //stisnut SVE-STOP, fatal err.

///////////////////////////////task pedale suceone punkt masine/////////////////////////////////////////
switch(ped_suc_seq_no){
case 0: //cekamo da bude pustena pedala suceonog
if(!pedala_suc)ped_suc_seq_no=0; //cekaj
else ped_suc_seq_no=1; //inace udji u proveru busy i stisnute
break;
case 1: //cekamo da bude stisnuta ako nije busy, inace ignorisi
if(!pedala_suc){ //stisnuta?
if(!var_busy_flag){ //ako nije zauzeto od klesta
var_busy_flag=1;semafor_red=1; //rezervisi trafo za suceoni, indikacija rada
suc_seq_jump=1;suc_seq_no=1; //aktiviraj task suceonog
ped_suc_seq_no=2; //idi na cekanje zavrsetka suceonog
}
else ped_suc_seq_no=0; //inace ignorisi pedalu, na pocetak za ponovni pokusaj
}
else ped_suc_seq_no=1; //inace cekaj da bude stisnuta
break;
case 2: //cekanje zavrsetka suceonog, ili njegove greske
if((suc_seq_no==8)||(suc_seq_no==7)){ //zavrsio suceoni, ili greska suceonog?
if(suc_seq_no==7)l_err_no=l_err_suceoni; //prijavi gresku suceonog, prekoracen polozaj, light err.
suc_seq_jump=0;suc_seq_no=0; //deaktiviranje taska suceonog
var_busy_flag=0;semafor_red=0; //oslobodi rezervaciju
ped_suc_seq_no=0; //vrati se na cekanje pedale
}
else ped_suc_seq_no=2; //inace cekaj
break;
}
//////////////////////////////////////////////////////////////////////////////////

///////////////////////////////task pedale klesta za punktovanje okvira/////////////////////////////////
switch(ped_kl_seq_no){
case 0: //cekamo da bude pustena pedala klesta
if(!pedala_kl)ped_kl_seq_no=0; //cekaj
else ped_kl_seq_no=1; //inace udji u proveru busy i stisnute
break;
case 1: // cekamo da bude stisnuta, ako nije busy, inace ignorisi
if(!pedala_kl){ //stisnuta?
if(!var_busy_flag){ //ako nije zauzeto od suceonog
var_busy_flag=1;semafor_yelow=1; //rezervisi klesta, tj. trafo
kl_seq_jump=1;kl_seq_no=1; //aktiviraj task klesta
ped_kl_seq_no=2; //idi na cekanje zavrsetka klesta
}
else ped_kl_seq_no=0; //inace ignorisi pedalu, na pocetak za ponovni pokusaj
}
else ped_kl_seq_no=1; //inace cekaj da bude stisnuta
break;
case 2: //cekanje zavrsetka klesta
if((kl_seq_no==6)||(kl_seq_no==5)){ //zavrsila klesta, ili greska?
if(kl_seq_no==5)l_err_no=l_err_klesta; //prijavi gresku, nedovoljan je pritisak, light err.
var_busy_flag=0;semafor_yelow=0; //oslobodi rezervaciju i vrati se na cekanje pedale
ped_kl_seq_no=0; //ovaj task u pocetni polozaj, stop
}
else ped_kl_seq_no=2; //inace cekaj
break;
}
////////////////////////////////////////////////////////////////////////////////

///////////////////////////////task oba tastera savijanja zice////////////////////////////////////////////
switch(tast_sav_seq_no){
case 0: //cekamo da oba tastera budu pustena
if((!tast1_sav)||(!tast2_sav))tast_sav_seq_no=0;//cekaj dok ne budu pustena oba
else tast_sav_seq_no=1; //inace idi na cekanje oba stisnuta
break;
case 1: //cekamo da oba budu stisnuta
if((!tast1_sav)&amp;&amp;(!tast2_sav)){ //stisnuta oba?
sav_seq_jump=1; sav_seq_no=1; //aktiviraj task savijanja
semafor_green=1; //indikacija rada
tast_sav_seq_no=2; //idi na cekanje zavrsetka savijanja
}
else tast_sav_seq_no=1; //inace cekaj da oba budu stisnuta
break;
case 2: //cekamo zavrsetak savijanja
if((sav_seq_no==6)||(sav_seq_no==5)){ //task savijanja zavrsio, ili greska?
if(sav_seq_no==5)l_err_no=l_err_savijanje; //prijavi gresku, istekao wdt, light err.
sav_seq_no=0; //stavi task savijanja u stop stanje
semafor_green=0;tast_sav_seq_no=0; //ukloni indikaciju i vrati se na pocetak
}
else tast_sav_seq_no=2; //inace cekaj
break;
}
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////task suceonog punkt aparata////////////////////////////////////////////
switch(suc_seq_no){
case 0: //stop, pasivno stanje
blokiraj_suc=0; stegni_suc=0;
break;
case 1: //blokiraj komad, t_blok_suc
if(suc_seq_jump){ //jednokratan prolaz
CCPR1L=param[pow_suc]; //dodeli snagu power jedinici od 15KVA
temp_per1=param[per_suc]; //uzmi potreban broj perioda zavarivanja iz parametara
timer10ms=param[t_blok_suc]; //dodeli timeru vreme blokiranja
blokiraj_suc=1; //pokreni cilindar blokiranja
timeout=0; //startuj timer
suc_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timeout){ //ispunjeno vreme blokiranja?
suc_seq_jump=1;suc_seq_no=2; //idi na stezanje komada
}
}
break;
case 2: //stegni, t_stez_suc
if(suc_seq_jump){ //jednokratan prolaz
stegni_suc=1; //pokreni cilindar stezanja
timer10ms=param[t_stez_suc]; //dodeli timeru vreme stezanja
timeout=0; //startuj timer
suc_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timeout)suc_seq_no=3; //ispunjeno vreme, idi na kontrolu mikroprekidaca polozaja
}
break;
case 3: //proveri mikroprekidac, ako JE, zavar stop, err_suceoni, inace zavari
if(!prek_suc)suc_seq_no=7; //greska, idi na poziciju greske?
else{
suc_seq_jump=1; suc_seq_no=4; //sve ok. idi na zavarivanje
}
break;
case 4: //zavari
if(suc_seq_jump){ //jednokratan prolaz
TR_jump=1; TRseq_no=1; //start sync taska i brojanja perioda, napajanje sa T i R faza
suc_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(TRseq_no==3){ //sync TR task zavrsio?
TRseq_no=0; //stavljanje TR taska u stop stanje
suc_seq_jump=1; suc_seq_no=5; //idi na poststezanje-hladjenje komada
}
}
break;
case 5: //poststezanje, hladjenje komada
if(suc_seq_jump){ //jednokratan prolaz
CCPR1L=0; //svedi snagu zaseka na nulu, dodatna sigurnost
timer10ms=param[t_hlad_suc]; //dodeli timeru vreme hladjenja
timeout=0; //startuj timer
suc_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timeout){ //isteklo vreme?
suc_seq_jump=1;suc_seq_no=6; //ispunjeno vreme idi dalje
}
}
break;
case 6: //pusti oba cilindra
if(suc_seq_jump){ //jednokratan prolaz
blokiraj_suc=0; stegni_suc=0; //iskljucenje oba cilindra
timer10ms=10; //vreme sigurnog odvajanja kontakta komada=100mS
timeout=0; //startuj timer
suc_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timeout)suc_seq_no=8; //idi na poziciju uspesnog zavrsetka
}
break;
case 7: //pozicija greske suceonog, stopiraj zavar i pusti oba cilindra
enable1=0; TRseq_no=0; blokiraj_suc=0; stegni_suc=0;
break;
case 8: //pasivno stanje, indikator uspesnog zavrsetka
blokiraj_suc=0; stegni_suc=0;
break;
}
/////////////////////////end task suceonog///////////////////////
//////////////////////////////////////////////////////////////////////////////////


////////////////////////task klesta za punktovanje///////////////////////////////////////////////
switch(kl_seq_no){
case 0: //stop, pasivno stanje
stegni_kl=0; //cilindar off
break;
case 1: //predstezanje i proveri pritisak
if(kl_seq_jump){ //jednokratan prolaz
stegni_kl=1; //aktiviraj cilindar
CCPR1L=param[pow_kl]; //dodeli snagu power grupi pomocu pwm
temp_per1=param[per_kl]; //dodeli power grupi broj perioda zavarivanja
timer10ms=param[t_stez_kl]; //navij timer na vreme predstezanja klesta
timeout=0; //startuj timer
kl_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{
if(timeout){ //inace se vrti ovde posle jednokratnog prolaza
if(!v_prit_klesta)kl_seq_no=5; //greska err_p_vazd
else{kl_seq_jump=1;kl_seq_no=2;} //inace zavari
}
}
break;
case 2: //zavari
if(kl_seq_jump){ //jednokratan prolaz
TR_jump=1;TRseq_no=1; //start sync taska i brojanja perioda, tj. start power grupe
kl_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(TRseq_no==3){ //zavrsio sync task?
TRseq_no=0; //stavljanje TR taska u stop stanje
kl_seq_jump=1;kl_seq_no=3; //idi na poststezanje, hladjenje
}
}
break;
case 3: //poststezanje, hladjenje
if(kl_seq_jump){ //jednokratan prolaz
CCPR1L=0; //svedi snagu pow. grupe na nulu, dodatna sigurnost, pwm=0
timer10ms=param[t_hlad_kl]; //navij timer na vreme hladjenja
timeout=0; //startuj timer
kl_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timeout){ //isteklo vreme?
kl_seq_jump=1;kl_seq_no=4; //idi na otpustanje cilindra
}
}
break;
case 4: //pusti cilindar
if(kl_seq_jump){ //jednokratan prolaz
stegni_kl=0; //deaktiviraj cilindar
timer10ms=20; //sigurnosno vreme ukidanja elektricnog kontakta komada, 200mS
timeout=0; //startuj timer
kl_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timeout)kl_seq_no=6; //idi na piziciju uspesnog zavrsetka
}
break;
case 5: //pozicija greske klesta
stegni_kl=0; //deaktiviraj cilindar za svaki slucaj, ako sam negde zaboravio
break;
case 6: //indikator uspesnog zavrsetka, pasivno stanje
stegni_kl=0; //deaktiviraj cilindar za svaki slucaj, ako sam negde zaboravio
break;
}
////////////////////////end task klesta//////////////////////////
///////////////////////////////////////////////////////////////////////////////////


////////////////////////task savijanja zice///////////////////////////
switch(sav_seq_no){
case 0: //stop, pasivno stanje
spusti_spoljne=0;spoljni_cil=0;unutras_cil=0; //svi cilindri off
break;
case 1: //zatvori spoljne
if(sav_seq_jump){ //jednokratan prolaz
spoljni_cil=1; //aktiviraj prvu fazu savijanja
timer_sav=0; //startuj timer kao WDT
sav_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timer_sav&gt;(param[wdt_sav]*10))sav_seq_no=5; //wdt, rezol. 100mS, na pozic.err
if(spoljni_su_in){ //prvo savijanje zavrseno?
sav_seq_jump=1;sav_seq_no=2; //idi na sledecu fazu savijanja
}
}
break;
case 2: //otvori spoljne i spusti ih dole
if(sav_seq_jump){ //jednokratan prolaz
spoljni_cil=0;spusti_spoljne=1; //aktiviraj potrebna stanja cilindara
timer_sav=0; //startuj timer
sav_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timer_sav&gt;50){ //fiksno vreme 500mS
sav_seq_jump=1;sav_seq_no=3; //idi na drugu fazu procesa
}
}
break;
case 3: //zatvori unutrasnje
if(sav_seq_jump){ //jednokratan prolaz
unutras_cil=1; //aktiviraj unutrasnje
timer_sav=0; //startuj timer kao WDT
sav_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{
if(timer_sav&gt;(param[wdt_sav]*10))sav_seq_no=5; //wdt, rezol. 100mS, na pozic.err
if(unutr_su_in){ //drugo savijanje zavrseno?
sav_seq_jump=1;sav_seq_no=4; //idi na pripremu za nov komad
}
}
break;
case 4: //otvori unutrasnje i digni spoljne
if(sav_seq_jump){ //jednokratan prolaz
spusti_spoljne=0;spoljni_cil=0;unutras_cil=0; //aktiviraj povratak u pocetne pozicije
timer_sav=0; //startuj timer
sav_seq_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(timer_sav&gt;100)sav_seq_no=6; //isteklo vreme povratka (1000mS), idi na indikator zavrsetka
}
break; //pozicija greske
case 5:
spusti_spoljne=0;spoljni_cil=0;unutras_cil=0; //off za svaki slucaj
break;
case 6: //indikator uspesnog zavrsetka
spusti_spoljne=0;spoljni_cil=0;unutras_cil=0; //off za svaki slucaj
break;
}
///////////////////////end task savijanja////////////////////////


///////////////////////TR sinhro i brojac perioda task, scr kontroler je TCA785////////////////////////////
switch(TRseq_no){
case 0: // stop, pasivno stanje power grupe
enable1=0;
break;
case 1: //cekamo prvi TR polutalas
if(TRsync){ //pozitivna tranzicija
TR_jump=1; TRseq_no=2;
}
break;
case 2: //drugi TR polutalas, siguran prolaz kroz nulu
if(TR_jump){ //jednokratan prolaz
if(temp_per1&gt;0)temp_per1--; //ako ima jos nepotrosenih perioda, umanji za jednu
enable1=1; //odobri power grupu 15KVA, sada i ubuduce
TR_jump=0; //spreci ponavljanje jednokratnog prolaza
}
else{ //inace se vrti ovde posle jednokratnog prolaza
if(!TRsync){ //negativna tranzicija
if(temp_per1&lt;1){ //potrosene sve periode?
TR_jump=0; TRseq_no=3; //idi na zavrsetak
}
else TRseq_no=1; //inace radi dok ne potrosis periode
}
}
break;
case 3: //indikator zavrsetka 1.power grupe, pasivno stanje
enable1=0; //zabrana SCR power grupe
break;
} /////////////////////end TR sinhro//////////////////////////////////////

if(l_err_no)disp_l_err(l_err_no); //obrada lajt gresaka, bez zaustavljanja druge dve masine

if(err_no){ //ka obradi fatalnih gresaka, opsti stop, izlaz iz polu/autom.
iskljuci_izlaze(); //iskljuci sve izlaze
auto_escape=1; //pripremi break while petlje
memo_brojac(pisi); //zapamti brojac, ako je u upotrebi
op_status=bazni; //ponisti status autom.

}
if(auto_escape)break; //prekini while
} ////////////////////////////////end while autom. rada //////////////////////////////////
/*-------------------------------------------------------------------*/
} //////////////////////////////////end autom. funkcije////////////////////////////
/*-------------------------------------------------*/

void main(void)
{

/////////////////////////////
processor_init(); //inicijalizacija (konfig) MCU
lcd_init(); //inicijalizacija LCD
semafor_red=1; //test alarm lampe i butovanja MCU
animate(message[0]); //reklamna animacija skrolujucim tekstom
lcd_goto(line2); //idi na liniju 2 LCD
lcd_puts(message[1]); //ime masine
delay_ms(1500); //vreme prikaza
lcd_clear(); //ocisti LCD
lcd_puts(message[2]); //ime firme
lcd_goto(line2);
delay_ms(3000); //vreme do kraja reklamne poruke
//ocisti_ee(); /* obavezno uraditi kod prvog upisivanja programa */
get_group(); //dohvati parametre iz eeprom
delay_ms(10);
memo_brojac(citaj); //preuzmi stanje brojaca iz eeprom
// if(opt_p&amp;&amp;(n&lt;2))opcija_p(); //opcija plati gazda! Za one koji su sumnjivi oko placanja
delay_ms(10);
TMR0ON=1; /* Ukljucen timer0 */
//TMR1ON=1; /* ukljucen timer1 */
lcd_clear(); //ocisti LCD
disp_base(); //prikazuj set baznih poruka
semafor_red=0; //iskljuci alarmnu lampu
CCPR1L=0; //pwm1=0
////////////////////////////////
while(1){ //radi
kb_sc_execute(); //sken i izvrsenje tastature, test rad i rucni rad
if((op_status==poluautom)||(op_status==autom))autom_rad(); //poluautomatski i automatski rad
}//end main while(1)
} //end main
///////////////////////////////////////////END programa////////////////////////////////
//line1297
//////////////////////////////////////////////////////////////////////////////
</pre>
<p>Iskusnijima će možda ovo nešto i koristiti, možda i ne,&nbsp; ali početnicima će sigurno razjasniti mogućnosti upravljanja pomoću prilično "siromašnog" 8 bit MCU i neke od načina za realizaciju.</p>
<p>&nbsp;</p>
<p>Početnici će to sve "pohvatati" iz komentara (a razbio sam se pišući ih samo za vas :-).</p>
<p>Kasnije će im biti jasnije (zanimljiv stih).</p>
<p>&nbsp;</p>
<p>Pozz</p>
<p>&nbsp;</p>
<p>P.S.</p>
<p>&nbsp;</p>
<p>Zaboravih da napomenem: iz hardverskih razloga za inpute koristim negativnu logiku, tj. if(!inputx) je pitanje tipa da li JESTE.</p>
Reply
#30
<p>Prethodni primer pokazuje da 8 bit MCU nisu uopšte naivni kako se misli, i sve dok se ne zahteva žešća i brza matematika, sa ciframa koje nisu celobrojne i veće od dva bajta, 8 bit MCU su stvarno potpuno dovoljni za prilično ozbiljne naprave.</p>
Reply
#31
<p>Nekom sledećom prilikom, kad dobijem vremena, objasniću jednu moju jednostavnu metodu za brzu hardversku konfiguraciju PLC sa MCU, gde se izbor "in" ili "out" izvodi samo prevrtanjem optokaplera na istoj pcb i stavljanjem potrebnih elemenata ka spoljašnjoj sredini. (otuda potiče korišćenje negativne logike za inpute)</p>
Reply
#32
<p>Što možeš noćas, ne ostavljaj za sutra...</p>
<p>&nbsp;</p>
<p>
[attachment=7426:in_out_config.pdf]</p>
<p>&nbsp;</p>
<p>Uz malo mašte možete sebi predočiti kako uraditi ostatak ka spoljašnjoj sredini:</p>
<p>&nbsp;</p>
<p>Mosfet, BJT, SCR, PNP input, NPN input, AC input, itd itd...</p>
<p>&nbsp;</p>
<p>Uz malo jumpera i pametne pcb to nije teško.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>


Attached Files
.pdf   in_out_config.pdf (Size: 11,68 KB / Downloads: 21)
Reply
#33
<blockquote class="ipsBlockquote" data-author="dlalkovic" data-cid="21336" data-time="1393149973">
<div>
<p>Moje pitanje skoro da nema veze sa tutorijalom, ali je ipak pitanje ( to se trazi u naslovu teme ).</p>
<p>U jednoj primeni potrebno je da izlazni pin ide direktno &nbsp;na ulazni pin ( koji prati pojavu prednje ivice sa izlaznog pina).</p>
<p>Kako optimalno povezati ova 2 pina?</p>
</div>
</blockquote>
<p>Pitanje je zašto povezivati ulazni pin na izlazni?</p>
<p>&nbsp;</p>
<p>Stanje izlaznog pina se može direktno saznati iz "LAT" registra.</p>
<p>&nbsp;</p>
<p>Dakle, na primer u C:</p>
<pre class="_prettyXprint">
If(output_pinX) uradi_nesto; // tako saznajes stanje, sa kasnjenjem od par stotina nS, sa 40MHz

//------------------------------------------------------------------------------

/* ako ti treba cekanje same tranzicije tog pina, i ako se ne bavis ni sa cim drugim u tom trenutku (MCU, ne ti :-) onda ovako: */

while(output_pinX); //cekamo da prestane prethodno pozitivno stanje
while(!output_pinX); //dogodila se silazna tranzicija
uradi_nesto; // dogodila se opet uzlazna tranzicija

// ili

while(!output_pinX); //cekamo da prestane prethodno negativno stanje
while(output_pinX); //dogodila se uzlazna tranzicija
uradi_nesto; // dogodila se opet silazna tranzicija

//--------------------------------------------------------------------------------

/* ako jos nesto obavljas u isto vreme (naravno opet MCU), onda ovako: */

unsigned char seq;

while(uslov){ //ovakva while "zuji" u krug sa par MHz, zavisno od kolicine toga u njoj.

radi_nesto_drugo_u_medjuvremenu; //sa korisnickog aspekta paralellni dogadjaj

switch(seq){
case 0:
if(!output_pinX)seq=1; //skoci u case 1 kada se dogodi silazak u nisko stanje
else seq=0; //inace cekaj
break;
case 1:
if(output_pinX)seq=2; //skoci u case 1 kada se dogodi uzlazna tranzicija
else seq=1; //inace cekaj
break;
case 2:
uradi_nesto; // uradi nesto na svaku uzlaznu tranziciju
seq=0; // vrati se na cekanje silazne
break;
}

radi_nesto_trece_u_medjuvremenu; //sa korisnickog aspekta paralellni dogadjaj

radi_nesto_N_u_medjuvremenu; //sa korisnickog aspekta paralellni dogadjaj

if(neki_uslov)break; //raskini while po potrebi

}
</pre>
<p>Kačenjem input pina na output pin, gubiš jedan pin bez potrebe, a ništa ne dobijaš na vremenu.</p>
<p>&nbsp;</p>
<p>Ali ako već želiš tako, onda input pin zakači na output pin kroz min. 220R.</p>
<p>Ako slučajno oba postaviš kao output, to će spasti MCU.</p>
<p>&nbsp;</p>
<p>Pozz</p>
Reply
#34

Jos jedan koristan komentar a koji je vezan sa slobodne nožice.

Po ovim tekstovima se uviđa da se vrlo "sitničari" za slobodne nožice, jedna nožica više-manje, što baš toliko pravimo pitanja oko toga Smile

Kada budete krenuli sa korišćenjem ovih PIC mikrokontrolera videćete da je svaka slobodna nožica zlata vredna Smile

Ovde se meša jedna nezgodna stvar a to je kada tamo vidite u specifikaciji da određeni PIC ima brdo nekih modula, I2C, USART, A/D i slično, kada se premota malo dalje specifikacija videćete tablicu gde je prikazano koji pin može da ima koje funkcije i tu iskače čest problem recimo da I2C port deli nožice sa USART (RS232) portom a kao za inat vam trebaju oba porta odjenom! I tu nema pomoći, mora da se izabere PIC sa više nožica gde su ti moduli razdvojeni.

Isto tako ICSP port (za programiranje) često deli port sa drugim seriskim modulima i ako bi hteli da koristite obe funkcije moralibi na PCB pločici da imate nekakve jumpere za prespajanje kada se programira i kada je u normalnom radu.

Dakle kada birate model PIC-a, dobro se prebrojite oko slobodnih nožica i pogledajte specifikaciju koje se funkcije dele!

Reply
#35
<p>Druže Macola, jedno pitanje&nbsp; Smile</p>
<p>&nbsp;</p>
<p>Ovakav način čekanja uzlazne tranzicije sa switch izgleda pomalo komplikovan, ali pretpostavljam da nije slučajno, pa se pitam da li je tako efikasnije ili zbog nečega drugog daje bolje rezultate nego kad bi se radilo recimo ovako, što na prvi pogled izgleda kraće</p>
<pre class="_prettyXprint">


unsigned char preth=1;

//...

if(output_pinx &amp;&amp; !preth) {

//uradi nesto

}
preth=output_pinx;</pre>
Reply
#36
<blockquote class="ipsBlockquote" data-author="enaB" data-cid="21392" data-time="1393242254">
<div>
<p>&nbsp;</p>
<p>Druže Macola, jedno pitanje&nbsp; Smile</p>
<p>&nbsp;</p>
<p>Ovakav način čekanja uzlazne tranzicije sa switch izgleda pomalo komplikovan, ali pretpostavljam da nije slučajno, pa se pitam da li je tako efikasnije ili zbog nečega drugog daje bolje rezultate nego kad bi se radilo recimo ovako, što na prvi pogled izgleda kraće</p>
<pre class="_prettyXprint">


unsigned char preth=1;

//...

if(output_pinx &amp;&amp; !preth) {

//uradi nesto

}
preth=output_pinx;</pre>
</div>
</blockquote>
<p>Skoro da nema razlike drugar. Oba koda će konzumirati sličan broj instrukcija posle kompajliranja, ako posmatramo samo saznavanje te jedne tranzicije.</p>
<p>&nbsp;</p>
<p>Ovo što si napisao izgleda kraće i elegantnije, dok ono sa switch obezbeđuje eksterni monitoring događaja praćenjem stanja varijable seq.</p>
<p>Switch je možda lakši za višestruki copy-paste, kada ima dosta toga. posle se samo izmene brojevi i untrašnjost.</p>
<p>&nbsp;</p>
<p>Kada se posmatra samo dva moguća događaja, onda switch nema nikakvih prednosti, ali ako je više od dva događaja, tri ili još više, kao na pimer:</p>
<p>&nbsp;</p>
<p>-da li ćekamo jednu tranziciju?</p>
<p>-da li čekamo drugu tranziciju?</p>
<p>-da li se događa izvršenje potrebnog?</p>
<p>&nbsp;</p>
<p>Tada switch dobija prednost lakog eksternog monitorisanja, od strane nekog drugog procesa, i nekog trećeg odlučivanja na osnovu njegovog trenutnog stanja, posmatranjem njegove varijable koja menja brojnu vrednost.</p>
<p>&nbsp;</p>
<p>Sve to veoma zavisi od konkretnog zahteva.</p>
<p>&nbsp;</p>
<p>Dlakovic je postavio nedovoljno precizan zahtev, pa sam napisao samo neki od mogućih primera (može to na još koji način).</p>
<p>&nbsp;</p>
<p>Prava pitanja, od kojih zavisi način, bi bila:</p>
<p>&nbsp;</p>
<p>-da li je potrebna samo prva uzlazna tranzicija?</p>
<p>-da li&nbsp; se posmatra svaka uzlazna?</p>
<p>-u kom vremenskom okviru se mora saznati događaj?</p>
<p>-šta treba uraditi posle detekcije?</p>
<p>-da li se za vreme izvršavanja potrebnog sme propustiti neka od sledećih tranzicija?</p>
<p>&nbsp;</p>
<p>-itd itd. bla bla....</p>
<p>&nbsp;</p>
<p>Šta je konačno efikasnije?&nbsp;</p>
<p>&nbsp;</p>
<p>-Što se pisanja tiče, ono gde se manje piše (bolji način kada nema frke sa procesorskim vremenom).</p>
<p>-Što se vremena izvršenja tiče, ono što će posle kompajliranja imati manje asm instrukcija (bolji način kada je frka sa vremenom, a ružniji za pisanje).</p>
<p>&nbsp;</p>
<p>Pozz</p>
Reply
#37
<p><span style="color:rgb(40,40,40);font-family:helvetica, arial, sans-serif;">Dlakovic je postavio nedovoljno precizan zahtev, pa sam napisao samo neki od mogućih primera (može to na još koji način).</span></p>
<p>&nbsp;</p>
<p><span style="color:rgb(40,40,40);font-family:helvetica, arial, sans-serif;">Da pojasnim zasto pin na pin. Izlazni pin je hardverski izlaz iz komparatora u PIC-u ( poredi testerast napon sa impulsom konstantne amplitude koji se periodicno vise puta &nbsp;pojavljuje u periodi testerastog napona ), a ulazni pin je konfigurisan da inkrementira TMR1 na prednju ivicu ( trenutak komparacije). Ovo treba da se izvrsava nezavisno od programa. U nekom trenutku citam tajmer i u njemu imam ukupan broj pozitivnih komparacija u nekom zadatom vremenskom periodu.</span></p>
Reko sam ti sve. a pomenuo te ne. ipak sada znaju svi. da si to ti
Reply
#38
<blockquote class="ipsBlockquote">
<p>&nbsp;</p>
<p><span style="color:rgb(40,40,40);font-family:helvetica, arial, sans-serif;">poredi testerast napon sa impulsom konstantne amplitude koji se periodicno vise puta &nbsp;pojavljuje u periodi testerastog napona</span></p>
</blockquote>
<p>Ako ti je impuls konstantne amplitude i poredis ga sa testerom uvek ces u istom trenutku imati tranziciju komparatora. Ne razumem bas najbolje ovo.</p>
Novac je sredstvo a ne cilj.
Reply
#39
<p>Hvala Smile</p>
Reply
#40
<blockquote class="ipsBlockquote" data-author="dlalkovic" data-cid="21412" data-time="1393261864">
<div>
<p><span style="color:rgb(40,40,40);font-family:helvetica, arial, sans-serif;">Dlakovic je postavio nedovoljno precizan zahtev, pa sam napisao samo neki od mogućih primera (može to na još koji način).</span></p>
<p>&nbsp;</p>
<p><span style="color:rgb(40,40,40);font-family:helvetica, arial, sans-serif;">Da pojasnim zasto pin na pin. Izlazni pin je hardverski izlaz iz komparatora u PIC-u ( poredi testerast napon sa impulsom konstantne amplitude koji se periodicno vise puta &nbsp;pojavljuje u periodi testerastog napona ), a ulazni pin je konfigurisan da inkrementira TMR1 na prednju ivicu ( trenutak komparacije). Ovo treba da se izvrsava nezavisno od programa. U nekom trenutku citam tajmer i u njemu imam ukupan broj pozitivnih komparacija u nekom zadatom vremenskom periodu.</span></p>
</div>
</blockquote>
<p>Ni meni nije baš jasno šta želiš.</p>
<p>&nbsp;</p>
<p>Otvaraju se nova pitanja:</p>
<p>-koji PIC je u pitanju?</p>
<p>-da li&nbsp; meriš frekvenciju?</p>
<p>-da li&nbsp; možda ne praviš diskretni A/D?</p>
<p>-da li možda ne "hvataš" neke stihijske pojave u određenom vremenskom intervalu?</p>
<p>-da li možda precizno meriš vreme imulsa?</p>
<p>-da li generišeš precizno vreme impulsa?</p>
<p>&nbsp;</p>
<p>Ne bi bilo loše da izložiš osnovnu ideju (ne moraš sve detalje ako je tajna), nacrtaš bar deo eksternog hardvera i možda talasne oblike koje očekuješ.</p>
<p>&nbsp;</p>
<p>Za sve ovo nabrojano postoje specijalizovani moduli u nekim od PIC, koji su hardverski i ne opterećuju program.</p>
<p>&nbsp;</p>
<p>Onda ti može sigurno više nas pomoći u rešavanju toga.</p>
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)