Modeliranje i upravljanje malom bespilotnom ronilicom · Potreba za istraživanjem, nadzorom i...
Transcript of Modeliranje i upravljanje malom bespilotnom ronilicom · Potreba za istraživanjem, nadzorom i...
SVEUCILIŠTE U ZAGREBUFAKULTET ELEKTROTEHNIKE I RACUNARSTVA
DIPLOMSKI RAD br. 404
Modeliranje i upravljanje malombespilotnom ronilicom
Marin Bek
Zagreb, veljaca 2012.
\izvornik.
iii
SADRŽAJ
1. Uvod 1
2. Razvojni sustav 32.1. Postavljanje toolchain-a . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2. Programiranje upravljacke elektronike . . . . . . . . . . . . . . . . . 4
2.2.1. Programiranje U-Boot boot loader na upravljacku elektroniku 5
2.2.2. Programiranje uClinuxa na upravljacku elektroniku . . . . . . 5
2.2.3. Kompajliranje uClinux image-a . . . . . . . . . . . . . . . . 6
2.2.4. Dodatne opcije - SD/MMC kartice . . . . . . . . . . . . . . . 11
3. Upravljacki sustav 133.1. Upravljacka elektronika propulzora . . . . . . . . . . . . . . . . . . . 16
3.1.1. Upravljanje strujom motora propulzora . . . . . . . . . . . . 18
3.1.2. Upravljanje brzinom vrtnje propulzora . . . . . . . . . . . . . 20
3.2. Upravljanje propulzorima . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.1. Mjerenje brzine vrtnje . . . . . . . . . . . . . . . . . . . . . 26
3.2.2. Upravljanje brzinom vrtnje - PWM . . . . . . . . . . . . . . 28
4. Inercijsko/navigacijski senzor 324.1. Korištenje spidev drivera . . . . . . . . . . . . . . . . . . . . . . . . 34
4.1.1. Korištenje spidev . . . . . . . . . . . . . . . . . . . . . . . . 35
5. Mehanicki sustav ronilice 39
6. Troškovi izrade ronilice 43
7. Proširenja i status ronilice 44
8. Zakljucak 45
iv
Literatura 46
A. Izvorni kod važnijih dijelova 48A.1. Upravljacki driver za pogon motora . . . . . . . . . . . . . . . . . . 48
A.2. Komunikacija s inercijskim senzorom . . . . . . . . . . . . . . . . . 57
A.3. IIO komunikacija . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
A.4. Patch za korištenje PWM-a iz korisnickog prostora . . . . . . . . . . 69
v
1. Uvod
Potreba za istraživanjem, nadzorom i kontrolom podmorja svakim je danom sve iz-
raženija, kako u industriji i vojsci, tako i u civilnim institucijama. Nalazišta nafte na
kopnu i priobalju se sve više primicu svom kraju, te se naftna industrija okrece dubo-
kom moru, što istraživanje, polaganje infrastrukture i nadzor otežava jer je sa svakim
metrom dubine skuplje imati ronioce, koji ujedno mogu i krace vrijeme provesti na
vecim dubinama. Dok je korištenje velikih industrijskih ronilica vec uhodana praksa,
njihovo korištenje za nadzor i istraživanje je neisplativo i neprakticno. Pojavila se
potreba za što je moguce manjim ronilicama, pogodnih za nadzor, cija bi niska ci-
jena omogucila korištenje i cijelih flota ronilica za pokrivanje veceg podrucja1, koje
bi u kooperaciji i formacijama efikasno i isplativno ispunjavale razlicite zadace bez
direktnog posredstva pilota. Nije off-shore industrija jedina zainteresirana za malim
isplativim autonomnim ronilicama. Vojna industrija je u potrazi za isplativim malim
ronilicama cija cijena je dovoljna da ih se može smatrati "topovskim mesom" u raz-
miniravanju podmorja. Naime, postoji koncept razminiravanja gdje vece površinsko
plovilo detektira moguca eksplozivna sredstva, a manje autonomne ronilice direktno
ili uz posredstvo ROV-ova provjeravaju autenticnost pronalaska, te aktiviraju ili de-
aktiviraju eksplozivna sredstva. U takvom je slucaju bitna stavka da je cijena što je
moguce manja uz zadovoljavajuce performanse. Mnoge su druge primjene minijatur-
nih autonomnih ronilica, poput nadzora luka, ušca rijeka, plovnih puteva... Bilo gdje
gdje je potrebno na isplativ i jednostavan nacin nadzirati vece podrucje, ili gdje su
klasicne ronilice jednostavno premalene za rad.
Iz navedenih je razloga u sklopu Završnog rada razvijena ronilica micro klase2. Ro-
nilica je cilindricnog oblika, dimenzija kucišta 21x8 cm, dok od prednjeg do stražnjeg
propulzora zauzima 30cm, a na najširem mjestu od 10 do 15 cm, ovisno o dimenzi-
jama montiranih propelera. Razvijena ronilica je predvidena za autonoman rad, te je
prototip, zbog cega osnovu upravljackog sustava drži relativno skup Blackfin hibridni
1eng. swarm2Ronilica malih dimenzija, mase u zraku do 3kg
1
DSP procesor3. Podržani su svi poznatiji komunikacijski protokoli za spajanje s pe-
riferijama (poput sonara i ostale senzorike), od cega je trenutno implementiran samo
3-osni inercijski senzor4. Propulzori su vlastitog dizajna, bazirani na brushless prin-
cipu rada i omogucuju rad pod vodom bez posebnih brtvila i semeringa. U sklopu ovog
rada, nastavlja se rad na toj ronilici, poboljšana je upravljacka elektronika za propul-
zore, implementirana je osnovna upravljacka funkcionalnost i dane su detaljne upute
za daljnji razvoj i korištenje ronilice.
3Procesor s generalnim RISC instrukcijama i DSP instrukcijama za obradu podataka4Analog Devices ADIS16350, 3-osni inercijski senzor sa SPI protokolom
2
2. Razvojni sustav
Pošto se na upravljackoj elektronici nalazi uClinux operativni sustav, sav razvoj kernel
modula, drivera i upravljackog softvera se mora vršiti na linux operativnim sustavima[1].
Službeno podržana okolina od strane proizvodaca Bluetechnix je XUbuntu, potvrdeno
cijela okolina radi s kernelom 2.6.38-8. Ukoliko korisnik nema na raspolaganju li-
nux operativni sustav, moguce je na Windowsima koristiti neko virtualno okruženje s
instaliranim linuxom. Na korisnickom DVD-u se nalazi vec gotova slika virtualnog
okruženja za VMWare sustav s instaliranim i podešenim cijelim razvojnim okruže-
njem.
Razvojno se okruženje sastoji od nekoliko dijelova:
• Toolchain - sadrži binarne, zaglavne i izvorne datoteke za kompajliranje apli-
kacija
• U-Boot - boot loader1
• uClinux - operacijski sustav temeljen na linux kernelu, prilagoden radu na
ugradbenim racunalima i real-time sustavima. Dolazi u sklopu toolchaina
Upozorenje: na korisnickom DVDu se nalazi verzija uClinuxa i pratecih paketa
(toolchain, uboot 2009R1. Razvoj trenutnog sustava je raden na verzijama 2010R1.
Kompatibilnost svih razvijenih drivera i modula, te aplikacija sa starijim verzijama
toolchaina nije zagarantirana i vjerojatno nije prisutna!
1"aplikacija" koja se pokrece prva prilikom paljenja sustava, ucitava operacijski sustav i postavlja
sve potrebne postavke na najnižoj razini
3
2.1. Postavljanje toolchain-a
Ako se ne koristi vec kreirano virtualno okruženje dano na DVDu (što je preporuceno,
pošto je u pitanju stara verzija toolchaina), potrebno je podesiti razvojno okruženje na
racunalu. Nakon što se preuzmu datoteke
• blackfin-toolchain-2010R1-RC4.i386.tar.bz2
• blackfin-toolchain-uclibc-full-2010R1-RC4.i386.tar.bz2
s lokacije http://blackfin.uclinux.org/gf/project/toolchain/
frs/, potrebno ih je otpakirati u neki direktorij i podesiti okruženje na nacin da se u
datoteku .bashrc (ili odgovarajucu) upiše
TOOLCHAINDIR=/home /marin /novo /opt /uClinux
e x p o r t PATH=$PATH :$TOOLCHAINDIR /bfin−uclinux /bin :$TOOLCHAINDIR /←bfin−elf /bin :$TOOLCHAINDIR /bfin−linux−uclibc /bin
Time je završeno podešavanje razvojne okoline.
2.2. Programiranje upravljacke elektronike
Pošto permanentno zapisivanje na flash memoriju u radu uClinux sustava nije moguce,
sve promjene poput drivera, librarya i ostalih datoteka koje želimo da su uvijek auto-
matski prisutne na ronilici prilikom pokretanja, potrebno je ukompajlirati u uClinux
image i isprogramirati na flash memoriju ronilice. Tako da je za razvoj ronilice esen-
cijalno poznavanje permanentnog programiranja pomocu JTAG adaptera.
Dva, tj. tri su važna dijela upravljackog sustava: boot loader, izvršni sustav (kernel)
i korisnicki prostor (root file system). Programiranje, tj. postavljanje binarnih datoteka
na sustav se vrši pomocu JTAG adaptera, i u nastavku je objašnjen postupak posebno
za boot loader i za kernel s korisnickim prostorom.
JTAG adapter korišten s upravljackom elektrnikom ronilice je ICEbear plus JTAG
adapter proizvodaca section5. Aplikacije za korištenje adaptera su dostupne na koris-
nickom DVD-u, ali se preporuca korištenje najnovije verzije dostupne s web-stranice
http://www.section5.ch/debian. Potrebno je preuzeti paket bfloader i
sve pratece upravljacke datoteke. Ukoliko se programira s linuxa, moguce je u dato-
teku /etc/apt/sources.list dodati liniju
4
deb http : / /www. s e c t i o n 5 . ch / d e b i a n < n a z i v i n s t a l i r a n e d i s t r i b u c i j e ←l i n u x a > main non−f r e e
i zatim korištenjem package managera instalirati pakete
• bfinsight - debugger
• bfloader - alat za programiranje
Na raspolaganju su još i razni alati za debuggiranje, ukoliko je to potrebno.
Instalacija na Windows operativnom sustavu je nešto jednostavnija, potrebno je
samo preuzeti s web-stranice instalacijski paket i instalirati ga.
Ukoliko se prilikom programiranja odabere pogrešna adresa ili binarna datoteka,
upravljacka elektronika se nece pravilno ukljuciti, ali je moguce ponoviti postupak
programiranja i na taj nacin ispraviti pogrešku.
2.2.1. Programiranje U-Boot boot loader na upravljacku elektro-niku
Na web-adresi navedenoj u prethodnom poglavlju moguce je naci i izvršne datoteke
boot loadera. Programiranje boot loadera na upravljacku elektroniku u principu ne bi
smjelo biti potrebno, osim ako postoji želja/potreba za update-om na noviju verziju.
Boot loader se najcešce nalazi u binarnoj datoteci imena u-boot.bin, i po-
trebno ga je smjestiti na pocetak flash memorije, što odgovara memorijskoj lokaciji
0x0000000.
2.2.2. Programiranje uClinuxa na upravljacku elektroniku
Svako kompajliranje uClinux-a rezultira s nekoliko vrsta binarnih datoteka:
• uImage - kernel + korisnicki prostor
• vmImage - samo kernel
• rootfs.jffs2 - samo korisnicki prostor
• uboot+uImage.bin - u-boot zajedno s kernelom i korisnickim prostorom.
U radu s upravljackom elektronikom ronilice zanima nas jedino datoteka uImage,
koja sadrži i kernel i korisnicki prostor zajedno. Kao što je ranije navedeno, svaka že-
ljena permanentna promjena na sustavu ronilice zahtjeva kompajliranje uClinux image-
a, i njegovo programiranje na flash memoriju ronilice.
5
uClinux image je potrebno smjestiti na memorijsku lokaciju 0x00040000.
2.2.3. Kompajliranje uClinux image-a
Operacijski sustav ronilice, uClinux, je temelj ispravnog rada ronilice, i zbog toga je
bitno poznavanje podešavanja opcija i mogucnosti kernela, jer se samim time odreduju
mogucnosti, performanse i postavke cijele upravljacke elektronike. Najbolje je odmah
nakon instalacije toolchaina pokušati iskompajlirati uClinux, prije svih promjena.
Kompajliranje uClinux imagea se vrši iz direktorija u kojem je instaliran toolchain,
najcešce naziva blackfin-linux-dist. Potrebno je u terminalu upisati
make menuconfig
što rezultira izbornikom
Vendor /Product Selection −−−>
Kernel /Library /Defaults Selection −−−>
−−−Load an Alternate Configuration File
Save an Alternate Configuration File
Odabir se vrši razmaknicom, zvjezdica znaci da je stavka odabrana, a u slucaju
kernel drivera, odabrana se stavka automatski ukljucuje u kernel, dok slovo M znaci
da se sprema na sustav kao modul (.ko), i potrebno ga je rucno ukljuciti naredbom
insmod.
Prvo je potrebno odabrati pravilan modul na elektronici. Pod izbornikom Vendor/Product
Selection je potrebno odabrati
−−− Select the Vendor you wish to target
Vendor (Bluetechnix ) −−−>
−−− Select the Product you wish to target
Bluetechnix Products (CM−BF537E ) −−−>
6
Kako bi se mogle birati opcije kernela i/ili korisnickog prostora (aplikacija), tako-
der je potrebno u izborniku Kernel/Library/Defaults Selection odabrati
−−− Kernel is linux−2 .6 .x
−−− Libc is None
[ ] Default all settings (lose changes )
[ ∗ ] Customize Kernel Settings
[ ∗ ] Customize Application /Library Settings
[ ] Update Default Vendor Settings
Izlazak iz svih izbornika rezultira pitanjem da li želite pohraniti promjene koje se
spremaju u datoteku .config, i mogu se kasnije ucitati iz izbornika. Ova se datoteka,
ispravno ispunjena, nalazi na CD-u priloženom ovom radu.
Ako je odabrano podešavanje postavki kernela, otvara se izbornik s postavkama
kernela
General setup −−−>
[ ∗ ] Enable loadable module support −−−>
[ ] Enable the block layer −−−>
Preemption Model (No Forced Preemption (Server ) ) −−−>
Blackfin Processor Options −−−>
Bus options (PCI , PCMCIA , EISA , MCA , ISA ) −−−>
Executable file formats −−−>
Power management options −−−>
CPU Frequency scaling −−−>
[ ∗ ] Networking support −−−>
Device Drivers −−−>
Firmware Drivers −−−>
File systems −−−>
Kernel hacking −−−>
Security options −−−>
< > Cryptographic API −−−>
Library routines −−−>
−−−Load an Alternate Configuration File
Save an Alternate Configuration File
7
Bitne stavke na koje je potrebno obratiti pozornost su
• Enable loadable module support - nije automatski odabrano
• CPU Frequency scaling - ukljucivanjem ove opcije omogucava se sma-
njivanje radne frekvencije procesora, i time štedi energija
• Device Drivers - razne pogonske datoteke, objašnjeno detaljnije kasnije
• Cryptographic API - moguce je sve iskljuciti
Moguce je npr. iskljuciti sve što ima veze s UART komunikacijom, CAN protoko-
lom, wireless mrežom itd. U dijelovima ovog rada koji se ticu pojedinih stavki biti ce
naglašeno kako moraju biti postavljene relevantne opcije kernela.
Nakon postavljanja svih opcija kernela, ako je u prvom izborniku bilo odabrano
podešavanje aplikacija, pokrece se izbornik za odabir korisnickih aplikacija, poput
shella, servisa itd:
Library Configuration −−−>
Core Applications −−−>
Flash Tools −−−>
Filesystem Applications −−−>
Network Applications −−−>
Miscellaneous Applications −−−>
BusyBox −−−>
Tinylogin −−−>
MicroWindows −−−>
Games −−−>
Miscellaneous Configuration −−−>
Debug Builds −−−>
Blackfin test programs −−−>
Blackfin app programs −−−>
Blackfin canned demos −−−>
Blackfin device drivers (Experimental ) −−−>
Blackfin build options −−−>
−−Load an Alternate Configuration File
Save an Alternate Configuration File
8
Shell koji se koristi na ronilici je BusyBox, pa je preporuceno u njegovim op-
cijama, pod CoreUtils ukljuciti osnovne naredbe poput ls, cd, chown... Takoder,
pošto je mjesto u flash memoriji ograniceno, potrebno je pripaziti pri korištenju velikih
library-a, poput crypto, ncurses i slicnih alata, koji nisu potrebni za rad s ronilicom a
zauzimaju relativno mnogo prostora.
Opcije koje su odabrane za trenutnu konfiguraciju ronilice se takoder nalaze na pri-
loženom CD-u, i preporuceno ih je koristiti (ucitati konfiguracijsku datoteku prilikom
prvog kompajliranja), kako bi se osigurao normalan rad ronilice.
Kad je odabir svih opcija završen, korisnik je vracen u shell, i ukoliko nema pri-
javljenih grešaka, moguce je pristupiti kompajliranju. Kompajliranje se zapocinje na-
redbom
make
Nakon uspješnog kompajliranja, kreirana je datoteka images/uImage, ali prije
programiranja iste na flash memoriju procesora, potrebno je napraviti izmjene na dato-
tecnom sustavu. U direktoriju romfs se nalazi cijeli datotecni sustav kakav se sprema
u flash memoriju. Na priloženom CD-u se takoder nalazi romfs direktorij, s poddirek-
torijem etc, u kojem su dvije datoteke:
• rc
• passwd.
Datoteka rc se pokrece prilikom pokretanja sustava, i kljucno je da se ova modi-
ficirana datoteka smjesti u direktorij blackfin-linux-dist/romfs/etc, kako
bi se ronilica prilikom pokretanja inicijalizirala na pravilnu IP adresu i upalila potrebne
servise. Sadržaj rc datoteke je kako slijedi:
9
hostname blackfin
mount −t proc proc /proc
mount −t ramfs ramfs /var
mount −t sysfs sysfs /sys
mount −t devpts devpts /dev /pts
[ −d /proc /bus /usb ] && mount −t usbfs usbfs /proc /bus /usb
[ −d /sys /kernel /debug ] && mount −t debugfs debugfs /sys /kernel /←debug
[ −d /proc /sys /fs /binfmt_misc ] && mount −t binfmt_misc ←binfmt_misc /proc /sys /fs /binfmt_misc
[ −d /sys /kernel /security ] && mount −t securityfs securityfs /sys←/kernel /security
grep −qs nfsd /proc /filesystems && mount −t nfsd nfsd /proc /fs /←nfsd
i f [ −e /bin /mdev ] ; then
echo /bin /mdev 2 >/dev /null > /proc /sys /kernel /hotplug
/bin /mdev −s 2> /dev /null
fi
mkdir /var /tmp /var /log /var /run /var /lock
ifconfig lo 1 2 7 . 0 . 0 . 1
ifconfig eth0 1 9 2 . 1 6 8 . 5 . 9 9 up
inetd &
cat /etc /motd
Ukoliko želimo da se i neki kernel modul/driver ukljuci prilikom pokretanja, a
nalazi se u /lib direktoriju kao .ko datoteka, možemo to uciniti dodavanjem linije npr.
modprobe ducky
Ako više kernel modula ovisi jedno o drugome, potrebno ih je ucitati redoslijedom
od onog o kojem ostali ovise.
Datoteka passwd je datoteka s korisnickim imenima i lozinkama, i ukoliko ne
želimo na ronilici koristiti lozinku root korisnika uClinux, možemo je spremiti kao
praznu tako da njen sadržaj zamjenimo s
10
root :$1$foSVZUyD$qcWQ6Iaud .SOntvVBKKtC / : 0 : 0 : root : / root : / bin /sh
nobody :x : 9 9 : 9 9 :Nobody : :
Ako želimo na ronilicu smjestiti još neke datoteke, koje nisu automatski ukompaj-
lirane, npr. upravljacke aplikacije koje razvijamo van toolchaina, možemo ih u ovom
trenutku smjestiti na odgovarajuca mjesta u romfs direktoriju.
Kad su promjene na romfs direktoriju završene, potrebno je komprimirati romfs
direktorij u uClinux image naredbom
make image
nakon cega u direktoriju images imamo funkcionalnu datoteku uImage koju
možemo isprogramirati na flash memoriju.
2.2.4. Dodatne opcije - SD/MMC kartice
Ako želimo dodati permanentnog prostora sustavu, možemo u kernel ukompajlirati
podršku za memorijske kartice SD/MMC, kroz opcije kernela
−−− MMC /SD /SDIO card support
[ ] MMC debugging (NEW )
[ ] Assume MMC /SD cards are non−removable (DANGEROUS ) (NEW )
∗∗∗ MMC /SD /SDIO Card Drivers ∗∗∗<M> SDIO UART /GPS c l a s s support
< > MMC host test driver (NEW )
∗∗∗ MMC /SD /SDIO Host Controller Drivers ∗∗∗< > Secure Digital Host Controller Interface support (NEW )
<M> MMC /SD /SDIO over SPI
te uz odabir željenog datotecnog sustava u izborniku File systems
11
[ ∗ ] Enable POSIX file locking API
[ ] Dnotify support
[ ∗ ] Inotify file change notification support
[ ∗ ] Inotify support f o r userspace
[ ] Quota support
< > Kernel automounter support
< > Kernel automounter version 4 support (also supports v3 )
< > FUSE (Filesystem in Userspace ) support
Caches −−−>
Pseudo filesystems −−−>
[ ∗ ] Miscellaneous filesystems −−−>
[ ] Network File Systems −−−>
<∗> Native language support −−−>
< > Distributed Lock Manager (DLM ) −−−>
12
3. Upravljacki sustav
Upravljacki sustav ronilice se sastoji od nekoliko razina, prikazanih slikom 3.1.
Najniža, hardverska razina upravljackog sustava je u sklopu Završnog rada bila re-
alizirana jednostavnim integriranim tranzistorskim H-mostovima3.21 bez strujne zaštite[3],
pri cemu se za upravljanje radom jedne faze motora koristila samo polovica svakog
mosta.
Takvo rješenje se pokazalo neucinkovitim, s jedne strane zbog korištenja previše
fizickog prostora unutar ronilice, a s druge zbog zastarjelosti klasicne tranzistorske
tehnologije na podrucju ucinske elektronike što je dovelo do više problema. Naime,
bipolarni tranzistori korišteni u implementiranom H-mostu imaju vlastiti pad napona
VCEsat od 1.8 do 4.9V. Taj se napon disipira u toplinu, što može rezultirati ukupnom di-
sipacijom od 25W [3]. Osim problema s discipacijom, odredeni utjecaj na cjelokupne
performanse ima i cinjenica da komutacijom motora upravlja centralna upravljacka
jedinica ronilice (Blackfin sklopovlje), što znaci da dragocjeno procesorsko vrijeme
odlazi na fundamentalno jednostavan zadatak prolaska kroz komutacijsku tablicu. Uz
to, utrošeno je i mnogo ulazno/izlaznih pinova Blackfin modula i time se ogranicilo
moguce kasnije proširenje funkcionalnosti cijele ronilice. Kako bi Blackfin modul
mogao upravljati H-mostovima jednog propulzora, potrebno je utrošiti 9 pinova: 3
za ocitavanje stanja Hall senzora i po 3 pina za ukljucivanje H-mosta, te stavljanje
mostova u stanje visoke impedancije. Dodamo li tome i 2 pina potrebna za potpuno
gašenje upravljacke elektronike (ENABLE pinovi), dolazimo do brojke od 11 ulaz-
no/izlaznih prikljucaka utrošenih na posao koji je moguce u potpunosti odvojiti od
centralnog upravljackog sklopovlja.
Sveukupno, prisutna su tri problema:
• Utrošak elektricne energije veci zbog vlastitog pada napona tranzistora
• Zagrijavanje komponenti zbog discipacije na tranzistorima
• Trošenje procesorskog vremena na upravljanje propulzijom, trošenje I/O pi-
1Elektricni krug 4 upravljana tranzistora/sklopke za gonjenje motora u oba smjera
13
Korisnicko sucelje/autopilot
Korisnik ili autopilot odreduju
željeni smjer gibanja ronilice
Upravljacki program
Kernel daemon zaprima naredbu o promjeni
reference ronilice, obraduje je u adek-
vatan oblik i proslijeduje je regulatoru
Regulator
Regulator temeljem podataka sa senzorike odreduje vektore
upravljanja propulzorima s obzirom na dobivenu referencu
Modul upravljanja motorima
Modul zaprima od regulatora informaciju o
željenim brzinama pojedinih propulzora.
Odreduju se PWM vrijednosti i upravljacki signali
za ucinsku elektroniku motora.
Ucinska elektronika
Elektronika direktno upravlja radom motora.
Ukljucuju/iskljucuju/koce se odgovarajuci propulzori,
odreduje smjer i izvršava unutarnja petlja
regulatora struje/momenta motora.
Slika 3.1: Upravljacki sustav ronilice
nova
Kako bi se sva tri problema riješila, i time poboljšao rad ronilice i omogucio ro-
14
Slika 3.2: Prvotna upravljacka elektronika propulzora
busniji rad cijelog sustava, upravljacka elektronika propulzora je zamijenjena suvre-
menijom tehnologijom, a upravljacka petlja brzine/momenta motora propulzora je re-
alizirana sklopovljem jednostavnom povratnom vezom koristeci operacijsko pojacalo
u ulozi komparatora/integratora, gdje centralni upravljacki modul daje samo referencu
brzine dobivenu iz regulatora, dok sklopovlje održava brzinu neovisno o centralnom
upravljackom modulu.
15
3.1. Upravljacka elektronika propulzora
Da bi se centralni modul rasteretio od komutacije i upravljanja brzinom propulzora,
upotrebljen je integrirani krug L6235, proizvodaca STMicroelectronics, s ugradenom
logikom za komutaciju motora. Uz to, ucinska elektronika odabranog integriranog
kruga je realizirana u MOSFET tehnologiji, vrlo niskog otpora RDS2, iznosa 0.28 −
0.59 Ω (25 − 125 C), što znaci da je disipacija u odnosu na ranije korištenu tehnolo-
giju svedena na minimum - nije potrebno dodatno hladenje, vec je dovoljno osigurati
odgovarajucu površinu bakrenog sloja na pinovima uzemljenja [2, 4]. Osnovne karak-
teristike L6235 su dane tablicom 3.1.
Tablica 3.1: Karakteristike integriranog kruga L6235 (SO24 pakiranje)
Velicina Opis Min. Max. Jedinica
VS Napon napajanja 12 52 V
VREF Referenca kruga upravljanja strujom motora -0.1 5 V
VSENSE Mjerni napon -6 6 V
IOUT Izlazna struja sklopa – 2.8 A
TJ Radna temperatura integriranog kruga -25 125 C
fSW Radna frekvencija – 100 kHz
Rth1 Termicki otpor s rashladnom površinom 6 cm2 – 51 C/W
Rth2 Termicki otpor bez rashladne površine i hladenja – 77 C/W
2Otpor izmedu drain i source prikljucaka MOSFET tranzistora, glavni "krivac" za disipaciju energije
na tranzistorima
16
Pošto se tri propulzora nalaze u stražnjem dijelu ronilice, a jedan u prednjem,
upravljacka elektronika je podijeljena na upravo te dvije sekcije. Elektricna shema
za upravljanje radom jednog propulzora je identicna u sva cetiri slucaja, s razlikom da
na stražnjoj elektronici sva tri integrirana kruga dijele RC generator pulsa, što je do-
zvoljeno i preporuceno za slucajeve do cetiri integrirana kruga [2]. Slika 3.4 prikazuje
elektricnu shemu za upravljanje jednim propulzorom.
1
1
2
2
3
3
4
4
D D
C C
B B
A A
1
*****1
Krug upravljanja BLDC motorom s kontrolom brzine* *
16.2.2012. 2:24:25D:\Dropbox\diplomski\altium\bldc_controller\controller.SchDoc
Title
Size: Number:
Date:File:
Revision:
Sheet ofTime:A4
H_11
DIAG2
SENSE_A 3
RCOFF4
OUT_1 5
GN
D6
GN
D7
TAC
HO
8
RC
PULS
E9
SENSE_B 10FWD/REV11
EN12
VREF13
BRAKE14
VB
OO
T15
OUT_3 16
VS_
B17
GN
D18
GN
D19
VS_
A20
OUT_2 21VC
P22
H_223
H_324
L6235PowerDIP24/SO24
U1L6235
VS
GND
GND
D1 BAV99
1R
R1
100R
R5MCHP06W2F1000T5E
10nF
C1102S43W103KV4E
220nF
C2
18125C224KAT2A
220nF
C3
18125C224KAT2A
GND
1nF
C111812PC102KAT1A
R6
TC33B-1-104E
GND
R7
TC33B-1-104E
GND
10nF
C4102S43W103KV4E
10nF
C5102S43W103KV4E
GND
100K
R8
CRCW1206100KFKEA
R9
GND
PULLUP
R10
10K
R11CRCW120610K0FKEA
10KR12
10KR13
1234
P2
MOLEX 22-05-3041
1 2 3 4 5
P1
22-05-3051
1K
R14CRCW12061K00FKEA
PULLUP
4K7
R15
CRCW12064K70FKEA
1MR16
CRCW12061M00FKEA
220nFC6
18125C224KAT2A
GND
PULLUP
100nF
C7CC1812KKX7RBBB104
5K6
R17
MCHP06W2F5601T5E
1K8
R18WCR1206-1K8FI
68n
C8GRM43QR72J683KW01L
1 23 4
P3
AMP - 826942-2
1nF
C91812PC102KAT1A
GND
2K2
R19
CRCW12062K20FKEA
20K
R20CRCW120620K0FKEA
PULLUP
R21
TC73X-1-502E
GND
100uF
C10
MAL215097803E3
123
P4
MKDSN2,5/3-5.08
1234
P5
MKDSN2,5/4-5.08
VS PULLUP
GND
Ulazni naponi
Zatvoreni krug upravljanja brzinom vrtnje
Konektor HALL senzora
Upravljački ulaz
Spoj motora
1R
R2
1R
R3
1R
R4MCHP06W2F100KT5E
2
31A
84
U2ALM2904ST
GND
VS
Net_SenseGND
Net_Sense
PIC101
PIC102COC1
PIC201PIC202
COC2
PIC301PIC302
COC3
PIC401
PIC402COC4
PIC501
PIC502COC5
PIC601PIC602
COC6
PIC701
PIC702COC7
PIC801
PIC802COC8
PIC901
PIC902COC9
PIC1001 PIC1002
COC10
PIC1101
PIC1102COC11
PID101PID102 PID103
COD1
PIP101 PIP102 PIP103 PIP104 PIP105
COP1
PIP201
PIP202
PIP203
PIP204
COP2
PIP301 PIP302
PIP303 PIP304
COP3
PIP401
PIP402
PIP403
COP4
PIP501
PIP502
PIP503
PIP504
COP5
PIR101
PIR102COR1
PIR201
PIR202COR2
PIR301
PIR302COR3
PIR401
PIR402COR4
PIR501
PIR502COR5
PIR60CCW
PIR60CWPIR60W
COR6
PIR70CCW
PIR70CWPIR70W
COR7
PIR801PIR802COR8
PIR901 PIR902COR9
PIR1001 PIR1002COR10
PIR1101 PIR1102COR11
PIR1201
PIR1202COR12
PIR1301
PIR1302COR13
PIR1401
PIR1402COR14
PIR1501PIR1502COR15
PIR1601PIR1602COR16
PIR1701PIR1702COR17
PIR1801
PIR1802
COR18PIR1901PIR1902COR19
PIR2001
PIR2002
COR20
PIR210CCW
PIR210CWPIR210W
COR21
PIU101
PIU102
PIU103
PIU104
PIU105
PIU106 PIU107PIU108 PIU109
PIU1010
PIU1011
PIU1012
PIU1013
PIU1014
PIU1015
PIU1016
PIU1017
PIU1018 PIU1019
PIU1020
PIU1021
PIU1022
PIU1023
PIU1024
COU1
PIU201
PIU202
PIU203
PIU204
PIU208 COU2A
PIC301
PIC401
PIC501
PIC701PIC801
PIC901
PIC1002
PIC1101
PIP102PIP503
PIP504
PIR101 PIR201 PIR301 PIR401
PIR60CCW
PIR70CCW
PIR1802
PIR210CCW
PIU106 PIU107 PIU1018 PIU1019
PIU204
NLGND
NLNet0SenseGND
PIR1401
PIR1502
PIU108
PIP403PIU1016
PIP402PIU1021
PIP401PIU105
PIP303
PIR1701PIR1801
PIP204
PIR1902
PIP203
PIR1301
PIU1014
PIP202 PIR802
PIP201
PIR1201PIU1011
PIP105PIR902
PIU1024
PIP104
PIR1002
PIU1023
PIP103
PIR1102
PIU101
PID101PIR502
PIC1102PIR60CWPIR60W
PIU104
PIC902
PIP301 PIP302
PIU1013
PIC802
PIP304
PIR1901
PIR2002
PIR210CWPIR210W
PIU203
PIC602
PIR1501
PIR1602
PIU202
PIC601
PIR1601
PIR1702PIU201
PIC502PIR801
PIU102
PIU1012
PIC402PIR70CWPIR70W
PIU109
PIC202
PID102
PIU1015
PIC102PIR501
PIC101
PIU1022
PIR102 PIR202 PIR302 PIR402PIU103
PIU1010 NLNet0Sense
PIC702
PIP101PIP502
PIR901
PIR1001
PIR1101
PIR1202 PIR1302
PIR1402
PIR2001
PIU208
PIC201
PIC302
PIC1001
PID103
PIP501
PIU1017PIU1020
NLVS
Slika 3.3: Elektricna shema sklopa za upravljanje jednim BLDC propulzorom
17
11
22
33
44
55
66
77
88
DD
CC
BB
AA
1
* * * * *1
Krug
upr
avlja
nja
BLD
C m
otor
om s
kont
rolo
m b
rzin
e*
*16
.2.2
012.
6:20
:53
D:\D
ropb
ox\d
iplo
msk
i\alti
um\b
ldc_
rear
\con
trolle
r_re
ar.S
chD
oc
Title
Size
:N
umbe
r:
Dat
e:Fi
le:
Revi
sion:
Shee
tof
Tim
e:A
4
H_1
1
DIA
G2
SEN
SE_A
3
RCO
FF4
OU
T_1
5
GND 6
GND 7
TACHO 8
RCPULSE 9
SEN
SE_B
10FW
D/R
EV11
EN12
VR
EF13
BRA
KE
14
VBOOT15
OU
T_3
16
VS_B17 GND 18
GND 19
VS_A20
OU
T_2
21
VCP22
H_2
23
H_3
24
L623
5Po
wer
DIP
24/S
O24
U1
L623
5
VS
GN
D
GN
D
D1
BAV
99
1RR14
10nF
C4
102S
43W
103K
V4E
100n
F
C5
CC
1812
KK
X7R
BB
B10
4
220n
F
C7
1812
5C22
4KA
T2A
GN
D
1nF
C2
1812
PC10
2KA
T1A
R7
TC33
B-1
-104
E GN
D
R13
TC33
B-1
-104
E GN
D
10nF
C8
102S
43W
103K
V4E
10nF
C1
102S
43W
103K
V4E
GN
D
100K
R2
CRCW
1206
100K
FKEA
R4
GN
D
PULL
UP R5 10K
R6
CRCW
1206
10K
0FK
EA
10K
R1
10K
R3
1 2 3 4 5
P_U
PR1
MO
LEX
22-
05-3
041
12345678
P_H
ALL
22-0
5-30
51
1KR11
CRCW
1206
1K00
FKEAPU
LLU
P
4K7
R12
CRCW
1206
4K70
FKEA
68n
C9
GR
M43
QR
72J6
83K
W01
L12
34
Pjum
p1
AM
P - 8
2694
2-2
1nF
C3
1812
PC10
2KA
T1A
GN
D
2K2
R8
CRCW
1206
2K20
FKEA
20K
R9
CRCW
1206
20K
0FK
EA
PULL
UP
R10
TC73
X-1
-502
E
GN
D
100u
F
C6
MA
L215
0978
03E3
VS
PULL
UPG
ND
Zatv
oren
i kru
g up
ravl
janj
a br
zino
m v
rtnje
Kon
ekto
r HA
LL se
nzor
a
Upr
avlja
cki u
laz
Spoj
mot
ora
1RR15
1RR17
1RR18
MCH
P06W
2F10
0KT5
E
POW
ERG
ND
VS
Net
_Sen
seG
ND
Net
_Sen
se
H_1
1
DIA
G2
SEN
SE_A
3
RCO
FF4
OU
T_1
5
GND 6
GND 7
TACHO 8
RCPULSE 9
SEN
SE_B
10FW
D/R
EV11
EN12
VR
EF13
BRA
KE
14
VBOOT15
OU
T_3
16
VS_B17 GND 18
GND 19
VS_A20
OU
T_2
21
VCP22
H_2
23
H_3
24
L623
5Po
wer
DIP
24/S
O24
U2
L623
5
VS
GN
D
GN
D1RR37
220n
F
C16
1812
5C22
4KA
T2A
220n
F
C19
1812
5C22
4KA
T2A
GN
D
1nF
C15
1812
PC10
2KA
T1A
R28
TC33
B-1
-104
E GN
D
R36
TC33
B-1
-104
E GN
D
10nF
C20
102S
43W
103K
V4E
10nF
C14
102S
43W
103K
V4E
GN
D
100K
R22
CRCW
1206
100K
FKEA
R25
PULL
UP R26 10K
R27
CRCW
1206
10K
0FK
EA
10K
R21
10K
R23
1 2 3 4 5
P_U
PR2
MO
LEX
22-
05-3
041
1KR34
CRCW
1206
1K00
FKEAPU
LLU
P
4K7
R35
CRCW
1206
4K70
FKEA
1MR
24
CRCW
1206
1M00
FKEA
220n
FC13 18
125C
224K
AT2
A
68n
C12
GR
M43
QR
72J6
83K
W01
L
12
34
Pjum
p2
AM
P - 8
2694
2-2
1nF
C17
1812
PC10
2KA
T1A
GN
D
2K2
R29
CRCW
1206
2K20
FKEA
20K
R31
CRCW
1206
20K
0FK
EA
PULL
UP
R33
TC73
X-1
-502
E
GN
D
Kon
ekto
r HA
LL se
nzor
a
Spoj
mot
ora
1RR38
1RR39
1RR40
MCH
P06W
2F10
0KT5
E
GN
D
VS
Net
_Sen
seG
ND
Net
_Sen
se2
net_
RC
2
net_
tach
o2
net_
RC
PULS
E2
net_
en2
net_
out2
1ne
t_ou
t22
net_
out2
3ne
t_ou
t11
net_
out1
2ne
t_ou
t13
net_
tach
o1
net_
ref1ne
t_vr
ef1
net_
vref
2
net_
h13
net_
h12
net_
h11
net_
h23
net_
h22
net_
h21
net_
fwd1
net_
brak
e1ne
t_en
1
net_
brak
e2ne
t_fw
d2
net_
refc
onn1
net_
refc
onn2
net_
enco
nn1
net_
enco
nn2
net_
vcp2
2 31
A4 11
U3A
LM32
4D
567
B4 11
U3B
LM32
4D
GN
D
PULL
UP
100n
F
C11
CC
1812
KK
X7R
BB
B10
4
1MR
16
CRCW
1206
1M00
FKEA
220n
FC10 18
125C
224K
AT2
A 5K6
R19
MCH
P06W
2F56
01T5
E
1K8
R20
WC
R12
06-1
K8F
I5K
6
R30
MCH
P06W
2F56
01T5
E
1K8
R32
WC
R12
06-1
K8F
I
net_
inv1
net_
cmp1
net_
cmp2
net_
inv2
100u
F
C18
MA
L215
0978
03E3
12345678910
P_pw
r
MK
DSN
2,5/
4-5.
08
iN
et C
lass
iN
et C
lass
iN
et C
lass
iN
et C
lass
iN
et C
lass
iN
et C
lass
iN
et C
lass
iN
et C
lass
ibo
ot
ibo
oti
boot
ibo
ot
PIC101PIC102COC
1
PIC201PIC202CO
C2
PIC301PIC302COC
3
PIC401PIC402CO
C4
PIC501
PIC5
02COC5
PIC601
PIC602
COC6 PI
C701
PIC702CO
C7
PIC801PIC802CO
C8
PIC901PIC902COC
9
PIC1
001
PIC1002COC10
PIC1101PIC1102COC11
PIC1201PIC1202COC12
PIC130
1PIC1302COC13
PIC1401PIC1402COC
14
PIC1501PIC1502COC
15
PIC160
1PIC
1602COC16
PIC1701PIC1702COC17
PIC1
801
PIC1
802
COC18 PI
C190
1PI
C190
2COC19
PIC2001PIC2002COC
20
PID101PID102
PID103
COD1
PIP0HALL01PIP0HALL02PIP0HALL0
3PIP0HALL04PIP0HALL05PIP0
HALL06PIP0HALL07PIP0HALL08
COP0HALL
PIP0pwr01PIP0pwr02PIP0p
wr03PIP0pwr04PIP0pwr05P
IP0pwr06PIP0pwr07PIP0pwr08
PIP0pwr09PIP0pwr010
COP0
pwr
PIP0
UPR1
01PI
P0UP
R102
PIP0
UPR1
03
PIP0
UPR1
04
PIP0
UPR1
05
COP0
UPR1
PIP0UP
R201
PIP0UP
R202
PIP0UP
R203
PIP0UP
R204
PIP0UP
R205
COP0
UPR2
PIPj
ump1
01PI
Pjump1
02
PIPj
ump1
03PI
Pjump1
04
COPjump1
PIPjum
p201
PIPj
ump2
02
PIPjum
p203
PIPj
ump2
04
COPj
ump2
PIR101PIR102COR
1
PIR201
PIR202COR
2
PIR301PIR302COR
3
PIR401
PIR402
COR4
PIR501
PIR502
COR5
PIR601
PIR602
COR6
PIR70CCWPIR70CWPIR70W
COR7
PIR801
PIR802COR
8
PIR901 PIR902
COR9
PIR100CCW
PIR100CWPIR100WCOR
10
PIR1101PIR1102COR
11
PIR1201 PIR1202COR12
PIR130CCWPIR130CWPIR130WCO
R13
PIR1401PIR1402 COR14 PIR1501PIR1502 CO
R15
PIR1
601
PIR1
602COR
16PIR1701PIR1702 COR17 PIR1801PIR1802 CO
R18
PIR1
901
PIR1902COR19
PIR2001 PIR2002COR20
PIR2101PIR2102COR
21
PIR2201
PIR220
2COR22
PIR2301PIR2302COR23
PIR2401
PIR2402COR24
PIR2
501
PIR2
502
COR25
PIR260
1PIR
2602
COR26
PIR2
701
PIR2
702
COR27
PIR280CCWPIR280CWPI
R280
WCOR28
PIR2901
PIR2
902COR29
PIR3001
PIR3002COR30
PIR3101 PIR3102COR31
PIR3201 PIR3202COR32
PIR330CCWPIR330CWPI
R330
WCOR33
PIR3401PIR3402COR34
PIR3501 PIR3502COR35
PIR360CCWPIR360CWPI
R360
WCOR36
PIR3701PIR3702 COR37 PIR3801PIR3802 CO
R38 PIR3901PIR3902 CO
R39 PIR4001PIR4002 COR
40
PIU101
PIU102
PIU103
PIU104
PIU105
PIU106
PIU107
PIU108
PIU109
PIU101
0
PIU1011
PIU1012
PIU1013
PIU1014
PIU1015
PIU101
6
PIU1017
PIU1018
PIU101
9
PIU1020
PIU1021
PIU1022
PIU1023
PIU1024
COU1
PIU201
PIU202
PIU203
PIU204
PIU205
PIU206
PIU207
PIU208
PIU209
PIU2010
PIU2011
PIU2012 PIU2013
PIU2014
PIU2015
PIU2016
PIU2017
PIU2018
PIU2019
PIU2020
PIU2021
PIU2022
PIU2023 PIU2024
COU2
PIU301
PIU302
PIU303
PIU304 PIU3011
COU3A
PIU304
PIU305
PIU306
PIU307
PIU3011
COU3B
PIC101
PIC201
PIC301
PIC602
PIC701 PIC801
PIC901
PIC1101
PIC1201
PIC1401
PIC1501
PIC1701
PIC1
802
PIC1
901 PIC2001
PIP0HALL02PIP0pwr06PIP0
pwr07
PIR70CCW
PIR100CCW
PIR130CCW
PIR1401PIR1501
PIR1701PIR1801
PIR2002
PIR280CCW
PIR3202PIR330CCW
PIR360CCW
PIR3701PIR3801
PIR3901PIR4001
PIU106
PIU107
PIU1018
PIU101
9
PIU206
PIU207
PIU2018
PIU2019
PIU3011
NLGN
D
NLNe
t0Se
nseG
ND
NLPO
WERG
ND
PIP0
UPR1
03
PIR301
PIU1014
NLnet0brake1
PIP0UP
R203
PIR2301
PIU2014
NLnet0brake2
PIC1
001
PIR1
601
PIR1902
PIU301NL
net0cmp1
PIC130
1
PIR2401
PIR3002
PIU307
NLnet0cmp2
PIC102PIR201
PIU102
PIU1012
NLnet0en1
PIC1402PIR2201
PIU202
PIU2012
NLnet0en2
PIP0
UPR1
02PIR202
NLnet0enconn1
PIP0UP
R202
PIR220
2NL
net0
enco
nn2
PIP0
UPR1
01
PIR101PIU101
1NLnet0fwd1
PIP0UP
R201
PIR2101PIU2
011NLnet0fwd2
PIP0HALL03
PIR602
PIU101
NLne
t0h1
1
PIP0HALL04
PIR502
PIU1023
NLnet0h12
PIP0HALL05
PIR402
PIU1024
NLnet0h13
PIP0HALL06
PIR2
702
PIU201
NLnet0h21
PIP0HALL07
PIR260
2
PIU2023
NLnet0h22
PIP0HALL08
PIR2
502
PIU2024
NLnet0h23
PIC1002
PIR1202
PIR1
602
PIU302
NLnet0inv1
PIC1302
PIR2402
PIR3502
PIU306
NLnet0inv2
PIP0pwr03
PIU105
NLnet0out1
1
PIP0pwr02
PIU1021
NLnet0out12
PIP0pwr01
PIU101
6
NLnet0out13
PIP0pwr010
PIU205
NLnet0out21
PIP0pwr09
PIU2021
NLnet0out22
PIP0pwr08
PIU2016
NLnet0out2
3
PIC1502PIR280CW
PIR2
80W
PIU204
NLne
t0RC
2
PIC2002PIR360CW
PIR3
60W
PIU209
NLne
t0RC
PULS
E2
PIC902
PIPj
ump1
04
PIR801
PIR902 PIR100CWPIR100W
PIU303
NLne
t0re
f1
PIP0
UPR1
04
PIR802
NLne
t0re
fcon
n1
PIP0UP
R204
PIR2
902
NLne
t0re
fcon
n2
PIR1402PIR1502
PIR1702PIR1802
PIU103
PIU101
0NLNet0Sense
PIR3702PIR3802
PIR3902PIR4002
PIU203
PIU2010
NLNe
t0Se
nse2
PIP0
UPR1
05
PIR1101
PIR1201PIU108 NLnet0tacho1
PIP0UP
R205
PIR3401
PIR3501PIU208 NLnet0tacho2PIU2
022NLnet0vcp2
PIC302
PIPj
ump1
01PI
Pjump1
02
PIU1013
NLne
t0vr
ef1
PIC1702
PIPjum
p201
PIPj
ump2
02
PIU2013
NLnet0vref2
PIC202PIR70CW
PIR70W
PIU104
PIC401 PIU1022PIC402PID101
PIC5
02
PIC160
2
PID102
PIU1015
PIU2015
PIC802PIR130CW
PIR130W
PIU109
PIC1202
PIPj
ump2
04
PIR2901
PIR3102 PIR330CWPI
R330
W
PIU305
PIPj
ump1
03
PIR1
901 PIR2001
PIPjum
p203
PIR3001 PIR3201
PIC1102
PIP0HALL01PIP0pwr05
PIR102PIR302
PIR401
PIR501
PIR601
PIR901
PIR1102
PIR2102PIR2302
PIR2
501
PIR260
1
PIR2
701
PIR3101
PIR3402
PIU304
PIC501
PIC601
PIC702
PIC160
1
PIC1
801
PIC1
902
PID103
PIP0pwr04
PIU1017
PIU1020
PIU2017
PIU2020
NLVS
Slika 3.4: Elektricna shema sklopa za upravljanje s dva BLDC propulzora
3.1.1. Upravljanje strujom motora propulzora
Integrirani krug L6235 sadrži VREF ulaz koji služi kao referenca internom sklopov-
lju strujnog regulatora, koji u kombinaciji sa SENSE ulazima cini krug upravljanja
strujom spojenog motora. SENSE-A i SENSE-B su nastavci izlaza MOSFET parova
na motore, te se na njih spaja precizni otpornik takav da maksimalna pretpostavlje-
na/željena struja kroz namote motora daje unaprijed poznati napon, uz što manji iznos
samog otpornika kako bi se minimizirali ukupni gubici i utrošak elektricne energije.
18
Slika 3.5: Upravljacka elektronika za pogon propulzora
Upravljanje strujom motora propulzora se tako može ostvariti PWM3 signalom s
centralnog upravljackog sustava. Poznavajuci iznosRsense otpornika znamo korelaciju
izmedu struje motora i napona na otporniku. Prilagodimo li naponskim djelilom (ot-
pornici R1 i R2 na slici 3.6) izlaz PWM signala s upravljackog sklopovlja, unutarnji
PWM sklop integriranog kruga L6235 ce prilagoditi iznos napona narinutog na svitke
motora. Upravljacka shema je dana slikom 3.6.
R2
R1+R2
L6235 PMW
upravljanje
MOSFET
sklopovlje
Upwm Uref e u Imot
Rsense
−
Usense
Slika 3.6: Upravljacki krug upravljanja strujom motora pomocu L6235
3eng. Pulse Width Modulation, Pulsno-širinska modulacija
19
Kako bi se visokofrekventni signal PWM-a mogao iskoristiti kao referenca, po-
trebno je niskopropusnim RC filtrom prilagoditi PWM signal [2], slika 3.7.
AN1625 APPLICATION NOTE
10/39
2.8 Reference Voltage for PWM Current Control
The device has an analog input, Vref, connected to the internal sense comparator, to control the peak value ofthe motor current through the integrated PWM circuitry. A fixed reference voltage can be easily obtained througha resistive divider from an available 5 V voltage rail (maybe the one supplying the µC or the rest of the applica-tion) and GND.
A very simple way to obtain a variable voltage without using a DAC is to low-pass filter a PWM output of a µC(see Figure 9).
Figu re 9. Obtaining a variable voltage through a PWM ou tput of a µC.
Assuming that the PWM output swings from 0 to 5V, the resulting average voltage will be
where DµC is the duty-cycle of the PWM output of the µC.
Assuming that the µC output impedance is lower than 1kΩ, with RLP = 56kΩ, RDIV = 15kΩ, CLP = 10nF and aµC PWM switching from 0 to 5V at 100kHz, the low pass filter time constant is about 0.12 ms and the remainingripple on the Vref voltage will be about 20 mV. Using higher values for RLP, RDIV and CLP will reduce the ripple,but the reference voltage will take more time to vary after changing the duty-cycle of the µC PWM, and too highvalues of RLP will also increase the impedance of the Vref net at low frequencies, causing a poor noise immunity.
As sensing resistor value is typically kept small, a small noise on Vref input pins might cause a considerable errorin the output current. It's then recommended to decouple this pin with a ceramic capacitor of some tens of nF,placed very close to Vref and GND pins. Note that Vref pin cannot be left unconnected, while, if connected toGND, zero current is not guaranteed due to voltage offset in the sense comparator. The best way to cut down(IC) power consumption and clear the load current is pulling down the EN pin. With very small reference voltage,PWM integrated circuitry can loose control of the current due to the minimum allowed duration of tON (see theProgrammable off-time Monostable section).
RLP
CLP
Vref
GND
PWM Output of a µC
RDIV
Vref5V DµC RDIV⋅ ⋅
RLP RDIV+-----------------------------------------=
Slika 3.7: AD konverzija PWM signala
3.1.2. Upravljanje brzinom vrtnje propulzora
Kako bi bilo moguce upravljati brzinom propulzora u zatvorenoj petlji, potrebno je
ostvariti mjerenje brzine okretanja motora. Pomocu internog monostabila L6235, mo-
guce je na izlazni prikljucak TACHO dobiti puls svaki puta kada Hall senzor 1 (ulaz
H1 integriranog kruga) okine. Time slijedi da je kutna brzina motora jednaka
ωm =2ftachon
[rad
s
], (3.1)
gdje je
ωm kutna brzina propulzora rad/s
ftacho frekvencija pulseva na TACHO izlazu Hz
n broj pari polova motora.
Trajanje pulsa odreduje se RC mrežom na RC-PULSE ulazu integriranog kruga,
prema izrazu
tpulse ' 0.6RPULSECPULSE, (3.2)
dok se vrijednosti RPULSE i CPULSE odreduju prema slici 3.8.
20
100 101 102
101
102
103
104
RPULSE = 100 kΩ
RPULSE = 47 kΩ
RPULSE = 20 kΩ
CPULSE [nF ]
t PULSE
[µs]
20 kΩ47 kΩ100 kΩ
Slika 3.8: Vrijednosti komponenti RC kruga TACHO sklopa
Pošto ce se motori koristiti u svrhe podvodne propulzije, moguce je pretpostaviti
da brzina vrtnje motora nece biti visoka, kao što je to slucaj pri radu u rijedem fluidu
(zraku). Zbog toga, trajanje pulsa tahometra može biti u srednjem rasponu. Time
se osigurava manji utjecaj EM4 smetnji na sklopovlje tahometra, a i smanjuje utjecaj
samog tahometra na ostale komponente. Odabrane i implementirane vrijednosti su
RPULSE = 47kΩ (3.3)
CPULSE = 10nF (3.4)
Integriranjem dobivenog signala možemo dobiti napon proporcionalan vrtnji mo-
tora, te ukoliko znamo da nam taj napon ima fiksni, unaprijed odredeni raspon, mo-
žemo komparatorom odrediti pogrešku [2]. Proslijedimo li tu pogrešku na VREF ulaz
L6235, odredujemo iznos struje namota motora i time utjecemo na zakretni moment
motora.
4Elektromagnetskih
21
AN1625 APPLICATION NOTE
26/39
Also the duty cycle of this signal, so its average value is proportional to the motor rotation speed. Simply inte-grating the square-wave a voltage proportional to the motor speed will be available to realize a speed loop, asin Figure 28: RPULSE and CPULSE define the fixed on-time (tPULSE) of the tacho output, integrated and comparedto a voltage proportional to the desired speed (Vspeed) by the op-amp; the output of the op-amp represents thespeed error signal. Providing this signal to the Vref input of the L6235, which sets the current in the motor wind-ings, the speed error will act on the motor modifying its torque, in order to maintain the speed at a constant value.R1 and R2 set the maximum current in the motor by limiting the voltage at the Vref pin.
Figure 28. Tacho output allows easy implementation of a speed loop.
Defining
KT Motor torque constant [Nm/A]
D Dynamic friction torque [Nms/rad]
J Motor + Load inertia moment [kgm2]
TR Load resistant torque [Nm]
τM = J/D Mechanical time constant [s]
n Number of polar couples
ωm Motor rotation speed [rad/s]
ftacho = nωm / 2π Tacho output frequency [Hz]
τI = Cfb · Rfb2 Integrator time constant [s]
Gop-amp = Rfb2 /Rfb1
Gw-v =Vpullup · n · tpulse / 2π [Vs/rad]
G1=R2 / RSENSE · (R1+R2) [1/Ω]
and neglecting the current ripple due to PWM control, the expression of the control loop transfer function (seeFigure 29) is:
RCPULSE TACHO
VrefL6235
CPULSE RPULSE
Rpullup
Cfb
Rfb2
R1
R2
VspeedtPULSE
Vpullup
Rfb1
H1 H2 H3
OUT1 OUT2 OUT3
BLDC Motor
VREF
VOP-AMP
VTACHO
RSENSE
SENSEA SENSEB
Slika 3.9: Upravljacki krug upravljanja brzinom motora
3.2. Upravljanje propulzorima
Svaki upravljacki konektor propulzora ima sljedece pinove:
Tablica 3.2: Upravljacki konektor
Pin Naziv Opis
1 DIR Smjer vrtnje - 1=CW
2 EN Enable
3 BRAKE Kocnica, nije spojeno
4 REF Referenca, PWM izlaz
5 TACHO Pin za mjerenje brzine vrtnje
Za upravljanje motorima je definirana upravljacka struktura
t y p e d e f s t r u c t
u n s i g n e d s h o r t id ;
u n s i g n e d s h o r t direction ;
u n s i g n e d s h o r t enable ;
22
/ / u n s i g n e d s h o r t b r a k e ;
u n s i g n e d s h o r t tacho ;
u n s i g n e d long tacho_clicks ;
t_control ;
Kocnica se ne koristi jer se u vodi motori momentalno zaustave pri gašenju zbog
gustoce medija, pa je na ovaj nacin uštedeno 4 IO ulaza procesora.
Upravljacka struktura je inicijalizirana adresama pinova na koje je spojena uprav-
ljacka elektronika pojedinih motora:
t_control motori [ ] =
1 , GPIO_PG0 , GPIO_PG2 , GPIO_PG6 , 0 ,
2 , GPIO_PG8 , GPIO_PG10 , GPIO_PG14 , 0 ,
3 , GPIO_PG4 , GPIO_PG12 , GPIO_PG1 , 0 ,
4 , GPIO_PG5 , GPIO_PG7 , GPIO_PG13 , 0
;
Driver prvo kreira /dev/ducky uredaj, pomocu kojeg zatim userspace aplikacije
mogu upravljati ronilicom:
s t a t i c i n t __init bfin_ducky_init ( vo id )
i n t ret ;
i n t i ;
/∗ Opce p o s t a v k e k e r n e l modula ∗ /
ret = platform_driver_register(&bfin_ducky_driver ) ;
i f (ret )
pr_init (KERN_ERR " u n a b l e t o r e g i s t e r d r i v e r \ n " ) ;
r e t u r n ret ;
bfin_ducky_device = platform_device_register_simple (←MODULE_NAME ,
−1, NULL , 0 ) ;
i f (IS_ERR (bfin_ducky_device ) )
pr_init (KERN_ERR " u n a b l e t o r e g i s t e r d e v i c e \ n " ) ;
23
platform_driver_unregister(&bfin_ducky_driver ) ;
r e t u r n PTR_ERR (bfin_ducky_device ) ;
. . .
Nakon što je driver kreiran, nastavlja se incijalizacija - svi gpio portovi na koje
su spojeni upravljacki pinovi se zahtjevaju od kernela na korištenje. Ukoliko to nije
moguce jer neki drugi dio sustava drži neki pin, ducky uredaj se uništava i javlja grešku.
Prilikom deaktivacije drivera, potrebno je osloboditi sve zauzete pinove, ugasiti
prekide i osigurati brisanje drivera iz liste uredaja:
24
s t a t i c vo id __exit bfin_ducky_exit ( vo id )
i n t i ;
del_timer(&timer_1 ) ;
/∗ g a s e n j e modula , moramo o s l o b o d i t i z a u z e t e r e s u r s e ∗ /
f o r (i=0; i<NMOTORS ; i++)
/ / g p i o _ f r e e ( m o t o r i [ i ] . b r a k e ) ;
gpio_free (motori [i ] . direction ) ;
gpio_free (motori [i ] . enable ) ;
free_irq (gpio_to_irq (motori [i ] . tacho ) , &motori [i ] ) ;
platform_device_unregister (bfin_ducky_device ) ;
platform_driver_unregister(&bfin_ducky_driver ) ;
25
3.2.1. Mjerenje brzine vrtnje
Upravljacka elektronika daje puls na tacho izlaz svaki puta kad hall senzor 1 okine,
što znaci da 6 puta u jednom okretaju motora dode signal na odgovarajuci gpio ulaz.
Inicijalizacijska funkcija drivera zahtjeva prekid na te signale, na nacin da svaki rastuci
brid odgovarajuceg pina pozove funkciju s argumentom o kojem se motoru radi:
# i f n d e f NO_RPMS
ret = request_irq (gpio_to_irq (motori [i ] . tacho ) , ←speed_counter , IRQF_TRIGGER_HIGH , " S p e e d c o u n t e r f o r ←ducky " , &motori [i ] ) ;
i f (ret )
printk (KERN_WARNING " IRQ %d i s n o t f r e e \ n " , ←gpio_to_irq (motori [i ] . tacho ) ) ;
r e t u r n ret ;
# e n d i f
Prekidna funkcija zatim broji pulseve i sprema ih u brojac odgovarajuceg propul-
zora:
s t a t i c irqreturn_t speed_counter ( i n t irq , vo id ∗motor )
/∗ t r ebamo malu pauzu da ne dobi jemo l a z n e s i g n a l e ∗ /
udelay ( 5 0 0 ) ;
( ∗ (t_control∗ )motor ) .tacho_clicks++;
r e t u r n IRQ_HANDLED ;
Potrebno je cekanje 500µs kako se istitravanja i spora prijelazna pojava pulsa ne
bi protumacili kao dodatni signali. Brojanje impulsa nije dovoljno, incijalizacija dri-
vera takoder postavlja i vremenski prekid koji svake sekunde pokrene drugu prekidnu
rutinu, koja izracunava RPM.
26
/∗ p o s t a v l j a m o t i m e r za r a c u n a n j e rpm i z t a c h o t i c k o v a na ←s v a k i h 1000ms ∗ /
tacho_clicks = 0 ;
setup_timer(&timer_1 , timer_func , 0 ) ;
ret = mod_timer(&timer_1 , jiffies + msecs_to_jiffies (SPEEDTIME←) ) ;
i f (ret )
pr_init (KERN_ERR " t i m e r f a i l e d \ n " ) ;
s t a t i c vo id timer_func ( u n s i g n e d long data )
i n t i ;
c h a r buff [ 3 0 ] ;
strcpy (message , " " ) ;
f o r (i=0; i<NMOTORS ; i++)
sprintf (buff , " rpm=%l u \ t \ t " , motori [i ] . tacho_clicks∗10) ;
strcat (message , buff ) ;
motori [i ] . tacho_clicks = 0 ;
msg = message ;
mod_timer(&timer_1 , jiffies + msecs_to_jiffies (SPEEDTIME ) ) ;
Ducky driver je u stvari character device driver, obicnim citanjem i pisanjem u/iz
ducky uredaja /dev/ducky se može komunicirati s driverom. Zbog toga svaki puta
kada driver izracuna RPM svih motora, te rezulate sprema u izlazni buffer naziva me-
ssage. Zatim, kada dode do zahtjeva za citanje od neke korisnicke aplikacije ili drugog
drivera, poziva se funkcija za citanje iz drivera, koja ranije kreiran buffer msg ispisuje
u izlazni buffer koji cita korisnik.
27
s t a t i c ssize_t bfin_ducky_read ( s t r u c t file ∗file ,
c h a r ∗buffer ,
size_t len ,
loff_t ∗offset )
i n t bytes_read = 0 ;
i f (∗msg == 0)
r e t u r n 0 ; / / end−of− f i l e
w h i l e (len && ∗msg )
put_user (∗msg , buffer ) ;
msg++;
buffer++;
len−−;
bytes_read++;
r e t u r n bytes_read ;
Korisnicke aplikacije motorima mogu upravljati tako da na uredaj /dev/ducky
zapišu podatak oblika
oNDE
gdje je
• o - znak
• N - redni broj motora, pocevši od 1
• D - Smjer vrtnje. 1 je u smjeru kazaljke na satu
• E - Enable
3.2.2. Upravljanje brzinom vrtnje - PWM
Referentni pinovi upravljackih elektronika su spojeni na pulsno-širinske (PWM) izlaze
procesora, i mijenjanjem širine pulsa mijenja se referentni napon.
Prije svega, potrebno je postaviti kernel opcije za korištenje timera, konkretno,
General Purpose Timers.
28
∗∗∗ Processor and Board Settings ∗∗∗CPU (BF537 ) −−−>
Silicon Rev ( 0 . 2 ) −−−>
System type (Bluetechnix CM−BF537E ) −−−>
BF537 Specific Configuration −−−>
Board customizations −−−>
Blackfin Kernel Optimizations −−−>
Kernel executes from (RAM ) −−−>
Memory model (Flat Memory ) −−−>
( 0 ) Turn on mmap ( ) excess space trimming before booting
−∗− Enable Blackfin General Purpose Timers API
Uncached DMA region (Enable 1M DMA region ) −−−>
∗∗∗ Cache Support ∗∗∗[ ∗ ] Enable ICACHE
[ ∗ ] Enable ICACHE f o r external memory
[ ∗ ] Enable DCACHE
[ ] Enable only 16k BankA DCACHE − BankB is SRAM
[ ∗ ] Enable DCACHE f o r external memory
External memory DCACHE policy (Write back ) −−−>
∗∗∗ Memory Protection Unit ∗∗∗[ ] Enable the memory protection unit (EXPERIMENTAL )
∗∗∗ Asynchronous Memory Configuration ∗∗∗EBIU_AMGCTL Global Control −−−>
EBIU_AMBCTL Control −−−>
Osim toga, prije kompajliranja kernela, potrebno je malo izmijeniti blackfin-linux-
dist/linux-2.6.x/drivers/char/bfin_simple_timer.c datoteku. Potrebno je izmijeniti ioctl
i timer funkcije prema sljedecem kodu
s t a t i c i n t timer_ioctl ( s t r u c t inode ∗inode , s t r u c t file ∗filp , ←uint cmd , u n s i g n e d long arg )
i n t minor = MINOR (inode−>i_rdev ) ;
u n s i g n e d long n ;
s w i t c h (cmd )
c a s e BFIN_SIMPLE_TIMER_SET_PERIOD :
i f (arg < 2)
r e t u r n −EFAULT ;
29
n = ( (get_sclk ( ) / 1000) ∗ arg ) / 1000 ;
set_gptimer_period (timer_code [minor ] . id , n ) ;
/ / s e t _ g p t i m e r _ p w i d t h ( t i m e r _ c o d e [ minor ] . id , n >> 1) ;
printk (DRV_NAME " : TIMER_SET_PERIOD : a r g=%lu , p e r i o d=%l u \ n←" ,
arg , n ) ;
b r e a k ;
c a s e BFIN_SIMPLE_TIMER_SET_WIDTH :
i f (arg < 2)
r e t u r n −EFAULT ;
n = ( (get_sclk ( ) / 1000) ∗ arg ) / 1000 ;
i f (n < 1)
printk ( " E r r o r 0% c y c l e n o t s u p p o r t e d ! \ n " ) ;
r e t u r n −EFAULT ;
i f (n > get_gptimer_period (timer_code [minor ] . id ) )
printk ( " Duty > p e r i o d n o t recommended ! \ n " ) ;
r e t u r n −EFAULT ;
set_gptimer_pwidth (timer_code [minor ] . id , n ) ;
printk (DRV_NAME " : TIMER_SET_WIDTH : a r g=%lu , p e r i o d=%l u \ n "←,
arg , n ) ;
b r e a k ;
c a s e BFIN_SIMPLE_TIMER_START :
set_gptimer_config (timer_code [minor ] . id , PWM_OUT | ←PERIOD_CNT | PULSE_HI ) ;
enable_gptimers (timer_code [minor ] . bit ) ;
b r e a k ;
c a s e BFIN_SIMPLE_TIMER_STOP :
disable_gptimers (timer_code [minor ] . bit ) ;
b r e a k ;
/∗ c a s e BFIN_SIMPLE_TIMER_READ :
∗ ( ( u n s i g n e d long ∗ ) a r g ) = i s r _ c o u n t [ minor ] ;
b r e a k ; ∗ /
d e f a u l t :
r e t u r n −EINVAL ;
r e t u r n 0 ;
30
s t a t i c i n t timer_open ( s t r u c t inode ∗inode , s t r u c t file ∗filp )
i n t minor = MINOR (inode−>i_rdev ) ;
i n t err = 0 ;
i f (minor >= MAX_BLACKFIN_GPTIMERS )
r e t u r n −ENODEV ;
/∗ e r r = r e q u e s t _ i r q ( t i m e r _ c o d e [ minor ] . i r q , t i m e r _ i s r , ←IRQF_DISABLED , DRV_NAME, ( vo id ∗ ) minor ) ;
i f ( e r r < 0 )
p r i n t k (KERN_ERR " r e q u e s t _ i r q (%d ) f a i l e d \ n " , t i m e r _ c o d e [←minor ] . i r q ) ;
r e t u r n e r r ;
∗ /
err = peripheral_request (translate_minor_to_pin (minor ) , ←DRV_NAME ) ;
i f (err )
printk (KERN_ERR " Timer p i n r e q u e s t f a i l e d ! \ n " ) ;
peripheral_free (translate_minor_to_pin (minor ) ) ;
r e t u r n err ;
printk ( " t i m e r %d pwm opened \ n " , minor ) ;
/ / s e t _ g p t i m e r _ c o n f i g ( t i m e r _ c o d e [ minor ] . id , OUT_DIS | PWM_OUT |←PERIOD_CNT | IRQ_ENA) ;
/ / p r_debug (DRV_NAME " : d e v i c e (%d ) opened \ n " , minor ) ;
r e t u r n 0 ;
Detaljan i cijelokupan ispis izmijenjene datoteke se nalazi u Dodatku.
31
4. Inercijsko/navigacijski senzor
Inercijsko navigacijski senzor korišten na ronilici je ADIS16350, spojen putem SPI
sabirnice na upravljacku elektroniku.
Kako bi se mogao koristiti, potrebno je postaviti SPI sabirnicu na procesoru. U
postavkama kernela to je u opcijama Device Drivers:
−−− SPI support
∗∗∗ SPI Master Controller Drivers ∗∗∗<∗> SPI controller driver f o r ADI Blackfin5xx
[ ] SPI bus lock
< > emulate SPI bus with Blackfin SPORT
< > Utilities f o r Bitbanging SPI masters
< > GPIO−based bitbanging SPI Master
< > Xilinx SPI controller common module
< > DesignWare SPI controller core support
< > ADIS16350 sensor driver
∗∗∗ SPI Protocol Masters ∗∗∗<M> User mode SPI device driver support
< > Infineon TLE62X0 ( f o r power switching )
User mode SPI device driver support je potrebno instalirati kao modul da bi se
omogucilo korištenje ili spidev drivera, ili službenog Analog Devices drivera.
32
Takoder pod Device Drivers, potrebno je postaviti
−−− Staging drivers
[ ] Exclude Staging drivers from being built
< > Line Echo Canceller support
∗∗∗ Qualcomm MSM Camera And Video ∗∗∗∗∗∗ Camera Sensor Selection ∗∗∗
< > GPIO driver support
< > POHMELFS filesystem support
RAR Register Driver −−−>
<M> Industrial I /O support −−−>
< > B .A .T .M .A .N . Advanced Meshing Protocol
< > STRIP (Metricom starmode radio IP )
< > Analog Devices ADIS16250 / 16255
i u Industrial IO Support
−−− Industrial I /O support
[ ∗ ] Enable ring buffer support within IIO
−M− Industrial I /O lock free software ring
−∗− Enable triggered sampling support
. . .
. . .
. . .
<M> Analog Devices ADIS16350 / 5 4 / 5 5 / 6 0 / 6 2 / 6 4 / 6 5 IMU SPI driver
Korištenje Staging drivera nije nužno, trenutno se ne koriste na ronilici zbog pro-
blema s akvizicijom podataka sa senzora, ali ukoliko se nade riješenje za taj problem,
korištenje Staging drivera je bolje od korištenja spidev drivera, nacina na koji se tre-
nutno komunicira sa senzorom.
33
4.1. Korištenje spidev drivera
Da bi se mogao koristiti spidev driver za komunikaciju s ADIS senzorom, nije dovoljno
samo odabrati njegovo kompajliranje u postavkama kernela, vec je potrebno podesiti i
opcije za kreiranje drivera u kodu. U direktoriju
blackfin−linux−dist /linux−2 .6 .x /arch /blackfin /mach−bf537 /boards
se nalazi datoteka cm_bf537e.c koju je potrebno modificirati tako da se nakon
linije
s t a t i c s t r u c t spi \_board \_info bfin \_spi \_board \_info [ ] \_ \←_initdata =
doda linije
# i f d e f i n e d (CONFIG \ _SPI \ _SPIDEV ) | | d e f i n e d (CONFIG \ _SPI \ _SPIDEV \←_MODULE)
.modalias = " s p i d e v " ,
.max \_speed \_hz = 300000 , /∗ max s p i c l o c k (SCK) speed←i n HZ ∗ /
.bus \_num = 0 ,
.chip \_select = 1 , /∗ CS , change i t f o r your boa rd ∗ /
.platform \_data = NULL , /∗ No s p i \ _ d r i v e r s p e c i f i c c o n f i g ←∗ /
.mode = SPI \_MODE \_3 ,
.irq = IRQ \_PG15 ,
,
# e n d i f
objašnjenje postavki:
• modalias - naziv drivera, mora biti spidev
34
• max_speed_hz - maksimalna brzina SPI sabirnice za uredaj. 300kHz je low-
power brzina za ADIS senzor, može ici do 2.5MHz
• bus_num - 0, jedina SPI sabirnica na procesoru
• chip_select - koji SPISEL signal se koristi. Chip-Select pin senzora je spojen
na pin 55, SPISEL1, pa je chip select=1
• mode - postavke SPI protokola, ADIS senzor radi u modu 3
• irq - pin na koji senzor daje signal pri svakom koraku uzorkovanja. Pin je
spojen na pin PG15
Nakon što su napravljene sve promjene, potrebno je iskompajlirati cijeli kernel!
Ako je sve uspješno izvršeno, na ronilici se u direktoriju /dev nalazi spidev0.1
uredaj.
4.1.1. Korištenje spidev
Uredaj spojen na SPI sabirnicu, za kojeg je definiran spidev driver se koristi poput
RAW datoteke:
# i n c l u d e < u n i s t d . h>
s t a t i c c o n s t c h a r ∗device = " / dev / s p i d e v 0 . 1 " ;
. . .
i n t ret = 0 ;
i n t fd ;
fd = open (device , O_RDWR ) ;
i f (fd < 0)
pabort ( " g r e s k a p r i o t v a r a n j u " ) ;
. . .
close (fd ) ;
Citanje podataka se vrši tako da se uredaju proslijedi adresa na kojoj se nalazi po-
datak koji želimo procitati. Tablica 4.1 prikazuje najvažnije adrese u izlaznom registru
35
senzora.
Ako se koristi spidev driver, potrebno je imati na umu da se radi o half-duplex1, što
znaci da su podaci u dolaznim registrima u stvari pomaknuti za jedan.
Tablica 4.1: Izlazni registar ADIS16350 senzora
Naziv Funkcija Adresa Duljina Format Skala
SUPPLY_OUT Napon napajanja 0x03 12b Binarni 1.8315mV
XGYRO_OUT Žiroskop - X 0x05 14b 2k 0.07326/s
YGYRO_OUT Žiroskop - Y 0x07 14b 2k 0.07326/s
ZGYRO_OUT Žiroskop - Z 0x09 14b 2k 0.07326/s
XACCL_OUT Akcelerometar - X 0x0B 14b 2k 2.2522mg
YACCL_OUT Akcelerometar - Y 0x0D 14b 2k 2.2522mg
ZACCL_OUT Akcelerometar - Z 0x0F 14b 2k 2.2522mg
XTEMP_OUT Temperatura - X 0x11 14b 2k 0.1453
YTEMP_OUT Temperatura - Y 0x13 14b 2k 0.1453
ZTEMP_OUT Temperatura - Z 0x15 14b 2k 0.1453
Nakon što je otvoren spidev uredaj, koristimo ioctl funkcije za prijenos poda-
taka. Struktura koja služi prijenosu je spi_ioc_transfer, koju inicijaliziramo na
sljedeci nacin:
\_ \_u16 buf ;
s t r u c t spi \_ioc \_transfer xfer ;
i n t ret ;
memset(&xfer , 0 , s i z e o f (xfer ) ) ;
xfer .tx_buf = ( \ _ \_u64 ) &buf ;
xfer .rx_buf = ( \ _ \_u64 ) &buf ;
xfer .len = 2 ;
xfer .speed \_hz = speed ;
xfer .bits \_per \_word = bits ;
xfer .cs \_change = 0 ;
xfer .delay \_usecs = 100 ;
1Nije moguce istovremeno primati i slati podatke
36
Senzor koristi 16bitni prijenos, zbog cega nam je buffer incijaliziran na 16bitni
podatak. Cijelu strukturu prvo postavimo na 0 kako bi osigurali da nema problema,
te zatim postavimo postavke prijenos - broj bajtova koji se prenose, brzinu prijenosa,
velicinu jednog podatka, vrijeme cekanja.
Ako želimo procitati podatak s adrese 0x03, postavimo podatak koji šaljemo na
buf = 0x0300 ;
Ako želimo na neku adresu upisati neki podatak, potrebno je dodati 0x8000 adresi,
a oblik slanja je takav da viša 2 bajta oznacuju adresu, a niža 2 bajta su podatak, npr
buf = 0x8000 + 0x3e02 ;
Slanje poruke se vrši ioctl pozivom SPI_IOC_MESSAGE() gdje je argument broj
podataka (16bitnih) koji se šalju.
ret = ioctl (fd , SPI \_IOC \_MESSAGE ( 1 ) , &xfer ) ;
i f (ret < 0)
pabort ( " P o g r e s k a p r i s l a n j u s p i poruke ! \ n " ) ;
37
Ukoliko želimo procitati više razlicitih adresa, možemo to uciniti odjednom, ima-
juci na umu da u tom slucaju rezultat prvog podatka ide u spremnik pod drugim podat-
kom itd.
memset (buf , 0 , s i z e o f (buf ) ) ;
buf [ 0 ] = 0x0300 ;
buf [ 1 ] = 0x0500 ; / / x a c l
buf [ 2 ] = 0x0700 ; / / y a c l
buf [ 3 ] = 0x0900 ; / / z a c l
buf [ 4 ] = 0x0b00 ; / / x gyro
buf [ 5 ] = 0x0d00 ; / / y gyro
buf [ 6 ] = 0x0f00 ; / / z gyro
read_data (xfer , 8 , fd ) ;
\beginlstlisting
gdje je read_data funkcija
\beginlstlisting
i n l i n e vo id read \_data ( s t r u c t spi \_ioc \_transfer∗ xfer , i n t len , ←i n t fd )
i n t ret ;
ret = ioctl (fd , SPI \_IOC \_MESSAGE (len ) , xfer ) ;
i f (ret < 0)
pabort ( " Problem sa s l a n j e m poruke ! \ n " ) ;
38
5. Mehanicki sustav ronilice
Nekoliko je promjena u odnosu na ronilicu dizajniranu u sklopu završnog rada:
• Poklopci ronilice su od aluminija, a ne više inoxa
• Promijenjeni su rotori propulzora (cvršci aluminij)
• Konektor nije komercijalni zbog prevelikih dimenzija, nego improviziran
Slika 5.1: Stražnji pogled na ronilicu
Konektori su realizirani s D-SUB konektorima - prednji konektor je VGA D-SUB
konektor, stražnji konektor je LPT 25pin D-SUB. Zaštita od vode je izvedena tako da
su konektori na poklopce ucvršceni industrijskim dvokomponentnim epoxyem, a unu-
tarnji izvodi su zalemljeni za kontakte i u potpunosti preliveni epoxyem. Motori, sen-
zori i ostali vanjski spojevi (napajanje, ethernet) imaju konektore zalivene epoxyem,
39
umetnute u utore konektora i zatim je sve zaliveno tekucim silikonom.
Ukoliko dode do potrebe da se neki od konektora išteka, vruci fen ili slican izvor
vruceg zraka može u dovoljnoj mjeri omekšati silikon da se može pokidati, a da se
epoxy sloj ne ošteti. Izvodi konektora su na slici 5.2, gledano izvana.
1
1
2
2
3
3
4
4
D D
C C
B B
A A
Title
Number RevisionSize
A4
Date: 16.2.2012. Sheet ofFile: D:\Dropbox\..\conn.SchDoc Drawn By:
1
20
2
21
3
22
4
23
5
24
6
25
7
8
9
10
11
12
13
14
15
16
17
18
19
27
26
Stra? nji konektor
GND
OU
T3O
UT2
OU
T1H
3H
2H
1
GND
VCC
V_POWER
OUT3OUT2OUT1
OU
T1O
UT2
OU
T3H
3H
2H
1
ETH
ERN
ET
H3
H2
H1
DESNI motor
LIJEVI motor
VE
RT
IKA
LN
I
PIJ?01
PIJ?02
PIJ?03
PIJ?04
PIJ?05
PIJ?06
PIJ?07
PIJ?08
PIJ?09
PIJ?010
PIJ?011
PIJ?012
PIJ?013
PIJ?014
PIJ?015
PIJ?016
PIJ?017
PIJ?018
PIJ?019
PIJ?020
PIJ?021
PIJ?022
PIJ?023
PIJ?024
PIJ?025
PIJ?026
PIJ?027
COJ?
NLETHERNETPIJ?021
PIJ?026
PIJ?027
NLGND
PIJ?04
PIJ?07
PIJ?023
NLH1
PIJ?03
PIJ?06
PIJ?011
NLH2
PIJ?05
PIJ?015
PIJ?024
NLH3
PIJ?017
PIJ?018
PIJ?019
PIJ?020
PIJ?02
PIJ?010
PIJ?013
NLOUT1
PIJ?01
PIJ?09
PIJ?012
NLOUT2
PIJ?08
PIJ?014
PIJ?025
NLOUT3
PIJ?016NLV0POWER
PIJ?022NLVCC
Slika 5.2: Stražnji konektor
40
Slika 5.3: Prednji pogled na ronilicu
41
Slika 5.4: Montaža prednje upravljacke elektronike na ronilicu
42
6. Troškovi izrade ronilice
U tablici 6.1 su dani okvirni troškovi izrade ronilice.
Tablica 6.1: Troškovi izrade ronilice
Rbr. Naziv Opis Cijena
1 ADSP bf537e Procesor 220e
2 EVAL-BF5xx Maticna ploca, periferija 300e
3 ADIS16350 Inercijski senzor 350e
4 PCB Izrada PCB-ova 50e
5 L6235 BLDC Driver 50e
6 SMD Komponente za upr. el. 20e
7 BLDC Žica, statori, rotori 80e
8 Mehanika Kucište 50e
9 Baterije Baterije 100e
Ukupno 1220e
Ukoliko nije potrebna DSP funkcionalnost, moguce je smanjiti trošak za i do 300e.
Moguca su i još dodatne manje uštede, ali cijena ronilice teško da bi mogla biti ispod
500e.
43
7. Proširenja i status ronilice
Ronilica je funkcionalna, sposobna za rad u vodi. Baterijski sustav nije implementiran,
ali su potrebne baterije smještene u kucište, i sva infrastruktura je prisutna.
Prvo i osnovno proširenje funkcionalnosti ronilice jesu kvalitetni, minijaturni po-
dvodni konektori, barem za spajanje vanjskog napajanja i komunikacijskog kabela.
Nadalje, potrebno je montirati propelere vece potisne površine, imajuci na umu ogra-
nicenja prostora. Potrebno je napomenuti da stražnji propulzor ima poteškoca zbog
necentriranosti, te je poželjno zamijeniti rotor novim.
Implementiran je inercijski sustav, ali nedostaje kvalitetan driver za rad u realnom
vremenu, sposoban za precizno deriviranje dobivenih vrijednosti u brzine i puteve.
Pošto je na raspolaganju i DSP procesor, te koder video signala, moguce je imple-
mentirati i racunalni vid, za aplikacije gdje je to potrebno.
44
8. Zakljucak
Postojeca ronilica je unaprijedena, upravljacka elektronika motora je u cijelosti izmi-
jenjena boljim rješenjem, implementirana je upravljacka logika za upravljanje propul-
zorima i inercijskim senzorom, te je mehanicki ronilica komplementirana. Pokazalo se
da je moguce izraditi veoma malenu ronilicu, dovoljno okretnu i brzu za nadzor i kon-
trolu. Izbaci li se skupa upravljacka elektronika, i zamijeni jeftinijim, jednostavnijijm
rješenjem, može se dobiti vrlo povoljna ronilica, pogodna za rad u flotama i sl.
45
LITERATURA
[1] Harald Krapfenbauer. Bluetechnix uclinux user guide, 2009.
[2] Vincenzo Marano. L6235 application note 1625, 2003. URL
http://www.st.com/internet/com/TECHNICAL_RESOURCES/
TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00004396.pdf.
[3] STMicroelectronics. L298 datasheet, Sijecanj 2000. URL http://www.
st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_
LITERATURE/DATASHEET/CD00000240.pdf.
[4] STMicroelectronics. L6235 datasheet, Rujan 2003. URL http://www.
st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_
LITERATURE/DATASHEET/CD00002347.pdf.
46
Modeliranje i upravljanje malom bespilotnom ronilicom
Sažetak
U radu je opisano korištenje minijaturne autonomne ronilice, dane su upute za
daljnji razvoj i proširenje implementiranih mogucnosti. Opisan je elektricki sustav
ronilice, upravljacki sustav i sva prateca softverska podrška.
Kljucne rijeci: ROV, AUV, ronilice, autonomno, sustavi za rad u realnom vremenu
Mathematical modelling and control of an autonomous underwater vehicle
Abstract
This thesis describes the usage of developed miniature AUV, and instructions on
further development of the said AUV. Electrical systems, control systems and all sof-
tware backend is included.
Keywords: ROV, AUV, underwater vehicles, autonomous systems, real-time systems
Dodatak AIzvorni kod važnijih dijelova
A.1. Upravljacki driver za pogon motora
/home/marin/src/modules/ducky/ducky.c
# i n c l u d e < l i n u x / module . h>
# i n c l u d e < l i n u x / k e r n e l . h>
# i n c l u d e < l i n u x / d e v i c e . h>
# i n c l u d e < l i n u x / p l a t f o r m _ d e v i c e . h>
# i n c l u d e < l i n u x / m i s c d e v i c e . h>
# i n c l u d e < l i n u x / t i m e r . h>
# i n c l u d e < l i n u x / i n t e r r u p t . h>
# i n c l u d e < l i n u x / e r r . h>
# i n c l u d e < l i n u x / f s . h>
# i n c l u d e < l i n u x / gp io . h>
# i n c l u d e < l i n u x / d e l a y . h>
# i n c l u d e <asm / u a c c e s s . h>
# d e f i n e p r _ d e v i n i t ( fmt , a r g s . . . ) \
( s t a t i c c o n s t __devinitconst c h a r __fmt [ ] = fmt ; \
printk (__fmt , ## args ) ; )
# d e f i n e p r _ i n i t ( fmt , a r g s . . . ) \
( s t a t i c c o n s t __initconst c h a r __fmt [ ] = fmt ; \
printk (__fmt , ## args ) ; )
t y p e d e f s t r u c t
48
u n s i g n e d s h o r t id ;
u n s i g n e d s h o r t direction ;
u n s i g n e d s h o r t enable ;
/ / u n s i g n e d s h o r t b r a k e ;
u n s i g n e d s h o r t tacho ;
u n s i g n e d long tacho_clicks ;
t_control ;
t_control motori [ ] =
1 , GPIO_PG0 , GPIO_PG2 , GPIO_PG6 , 0 ,
2 , GPIO_PG8 , GPIO_PG10 , GPIO_PG14 , 0 ,
3 , GPIO_PG4 , GPIO_PG12 , GPIO_PG1 , 0 ,
4 , GPIO_PG5 , GPIO_PG7 , GPIO_PG13 , 0
;
/ / # d e f i n e NO_RPMS
s t a t i c u n s i g n e d long tacho_clicks ;
# d e f i n e NMOTORS 4
# d e f i n e SUCCESS 0
s t a t i c s t r u c t timer_list timer_1 ;
# d e f i n e SPEEDTIME 1000
/∗ ADIS s e n z o r ∗ /
# d e f i n e ADIS_INTERRUPT GPIO_PG15
# d e f i n e GRAV 2 . 5 2 2∗9 . 8 0 6 7 6 / 1 0 0 0
# d e f i n e GYRO 0.07326
# d e f i n e VOLTAGE 1 . 8 3 1 5 / 1 0 0 0
s t a t i c c o n s t c h a r ∗device = " / dev / s p i d e v 0 . 1 " ;
s t a t i c uint8_t mode = 3 ;
s t a t i c uint8_t bits = 1 6 ;
s t a t i c uint32_t speed = 300000;
s t a t i c uint16_t delay = 5 0 ;
s t a t i c i n t inu_fd ;
s t a t i c c h a r ∗msg ;
s t a t i c c h a r message [ 5 0 ] ;
49
s t a t i c i n t device_open = 0 ;
s t a t i c i n t bfin_ducky_open ( s t r u c t inode ∗inode ,
s t r u c t file ∗file )
i f (device_open )
r e t u r n −EBUSY ;
device_open++;
try_module_get (THIS_MODULE ) ;
r e t u r n SUCCESS ;
s t a t i c i n t bfin_ducky_release ( s t r u c t inode ∗inode , s t r u c t file ∗←file )
device_open−−;
module_put (THIS_MODULE ) ;
r e t u r n 0 ;
s t a t i c ssize_t bfin_ducky_write ( s t r u c t file ∗file , c o n s t c h a r ←__user ∗data ,
size_t len , loff_t ∗ppos )
i f (data [ 0 ] == ’ o ’ )
gpio_set_value (motori [data [ 1 ] − ’ 1 ’ ] . direction , data [ 2 ] − ←’ 0 ’ ) ;
gpio_set_value (motori [data [ 1 ] − ’ 1 ’ ] . enable , data [ 3 ] − ’ 0 ’←) ;
/ / g p i o _ s e t _ v a l u e ( m o t o r i [ d a t a [ 1 ] − ’ 1 ’ ] . b rake , d a t a [ 4 ] − ←’ 0 ’ ) ;
r e t u r n len ;
s t a t i c ssize_t bfin_ducky_read ( s t r u c t file ∗file ,
c h a r ∗buffer ,
size_t len ,
50
loff_t ∗offset )
i n t bytes_read = 0 ;
i f (∗msg == 0)
r e t u r n 0 ; / / end−of− f i l e
w h i l e (len && ∗msg )
put_user (∗msg , buffer ) ;
msg++;
buffer++;
len−−;
bytes_read++;
r e t u r n bytes_read ;
s t a t i c c o n s t s t r u c t file_operations bfin_ducky_fops =
.owner = THIS_MODULE ,
.llseek = no_llseek ,
.write = bfin_ducky_write ,
/ / . u n l o c k e d _ i o c t l = b f i n _ w d t _ i o c t l ,
.open = bfin_ducky_open ,
.read = bfin_ducky_read ,
.release = bfin_ducky_release
;
s t a t i c s t r u c t miscdevice bfin_ducky_miscdev =
.minor = WATCHDOG_MINOR ,
.name = " ducky " ,
.fops = &bfin_ducky_fops ,
;
# d e f i n e MODULE_NAME " b f i n−ducky "
/∗ ∗∗ b f i n _ d u c k y _ p r o b e − I n i t i a l i z e module
∗ R e g i s t e r s t h e misc d e v i c e . A c t u a l d e v i c e
∗ i n i t i a l i z a t i o n i s h a n d l e d by b f in_ducky_open ( ) .
∗ /
s t a t i c i n t __devinit bfin_ducky_probe ( s t r u c t platform_device ∗pdev←)
51
i n t ret ;
ret = misc_register(&bfin_ducky_miscdev ) ;
i f (ret )
pr_devinit (KERN_ERR " c a n n o t r e g i s t e r miscdev ( e r r=%d ) \ n " ,
ret ) ;
r e t u r n ret ;
pr_devinit (KERN_INFO " i n i t i a l i z e d s u c c e s s f u l l y \ n " ) ;
r e t u r n 0 ;
/∗ ∗∗ bf in_ducky_remove − I n i t i a l i z e module
∗∗ U n r e g i s t e r s t h e misc d e v i c e . A c t u a l d e v i c e
∗ d e i n i t i a l i z a t i o n i s h a n d l e d by b f i n _ d u c k y _ c l o s e ( ) .
∗ /
s t a t i c i n t __devexit bfin_ducky_remove ( s t r u c t platform_device ∗←pdev )
misc_deregister(&bfin_ducky_miscdev ) ;
r e t u r n 0 ;
/∗ ∗∗ bf in_ducky_shu tdown − S o f t Shutdown Hand le r
∗∗ Handles t h e s o f t shutdown e v e n t .
∗ /
s t a t i c vo id bfin_ducky_shutdown ( s t r u c t platform_device ∗pdev )
s t a t i c s t r u c t platform_device ∗bfin_ducky_device ;
s t a t i c s t r u c t platform_driver bfin_ducky_driver =
.probe = bfin_ducky_probe ,
.remove = __devexit_p (bfin_ducky_remove ) ,
52
.shutdown = bfin_ducky_shutdown ,
/ / . su spend = b f i n _ d u c k y _ s u s p e n d ,
/ / . resume = bf in_ducky_resume ,
.driver =
.name = MODULE_NAME ,
.owner = THIS_MODULE ,
,
;
s t a t i c i n t __init request_gpio ( i n t gpio , i n t direction )
i n t ret ;
ret = gpio_request (gpio , " ducky d r i v e r " ) ;
i f (ret )
pr_init (KERN_ERR " u n a b l e t o r e q u e s t gp io \ n " ) ;
r e t u r n ret ;
e l s e
pr_init (KERN_INFO " r e g i s t e r e d gp io \ n " ) ;
i f (direction == 1)
gpio_direction_output (gpio , 1 ) ;
e l s e
gpio_direction_input (gpio ) ;
r e t u r n ret ;
s t a t i c irqreturn_t adis_interrupt ( i n t irq , vo id ∗handle )
r e t u r n IRQ_HANDLED ;
s t a t i c irqreturn_t speed_counter ( i n t irq , vo id ∗motor )
/∗ t r ebamo malu pauzu da ne dobi jemo l a z n e s i g n a l e ∗ /
udelay ( 5 0 0 ) ;
( ∗ (t_control∗ )motor ) .tacho_clicks++;
r e t u r n IRQ_HANDLED ;
s t a t i c vo id timer_func ( u n s i g n e d long data )
i n t i ;
c h a r buff [ 3 0 ] ;
53
strcpy (message , " " ) ;
f o r (i=0; i<NMOTORS ; i++)
sprintf (buff , " rpm=%l u \ t \ t " , motori [i ] . tacho_clicks∗10) ;
strcat (message , buff ) ;
motori [i ] . tacho_clicks = 0 ;
msg = message ;
mod_timer(&timer_1 , jiffies + msecs_to_jiffies (SPEEDTIME ) ) ;
/∗ ∗∗ b f i n _ d u c k y _ i n i t − I n i t i a l i z e module
∗∗ Checks t h e module params and r e g i s t e r s t h e p l a t f o r m d e v i c e & ←
d r i v e r .
∗ Real work i s i n t h e p l a t f o r m probe f u n c t i o n .
∗ /
s t a t i c i n t __init bfin_ducky_init ( vo id )
i n t ret ;
i n t i ;
/∗ Opce p o s t a v k e k e r n e l modula ∗ /
ret = platform_driver_register(&bfin_ducky_driver ) ;
i f (ret )
pr_init (KERN_ERR " u n a b l e t o r e g i s t e r d r i v e r \ n " ) ;
r e t u r n ret ;
bfin_ducky_device = platform_device_register_simple (←MODULE_NAME ,
−1, NULL , 0 ) ;
i f (IS_ERR (bfin_ducky_device ) )
pr_init (KERN_ERR " u n a b l e t o r e g i s t e r d e v i c e \ n " ) ;
platform_driver_unregister(&bfin_ducky_driver ) ;
r e t u r n PTR_ERR (bfin_ducky_device ) ;
/∗ I n t e r r u p t za p o d a t k e sa INU s e n z o r a ∗ /
/∗ i n u _ f d = open ( dev i ce , O_RDWR) ;
i f ( i n u _ f d < 0)
54
p r _ i n i t (KERN_ERR " u n a b l e t o open s p i d e v f o r a d i s \ n " ) ;
r e t u r n −1;
r e t = r e q u e s t _ i r q ( g p i o _ t o _ i r q ( ADIS_INTERRUPT ) , a d i s _ i n t e r r u p t ,←IRQF_TRIGGER_HIGH , "INU s e n s o r i n t e r r u p t h n d l r " , &i n u _ f d ) ;
i f ( r e t )
p r i n t k (KERN_WARNING "IRQ %d i s n o t f r e e \ n " , g p i o _ t o _ i r q (←ADIS_INTERRUPT ) ) ;
r e t u r n r e t ;
∗ /
/∗ t r a z i m o gp io p r a v a na u p r a v l j a c k e p in ov e s v i h motora .
∗ p o c e t n e p o s t a v k e su : i s k l j u c e n chip , CW smjer , i s k l j u c e n a ←k o c n i c a ∗ /
f o r (i=0; i<NMOTORS ; i++)
request_gpio (motori [i ] . direction , 1 ) ;
request_gpio (motori [i ] . enable , 1 ) ;
/ / r e q u e s t _ g p i o ( m o t o r i [ i ] . b rake , 1 ) ;
gpio_set_value (motori [i ] . direction , 1 ) ;
gpio_set_value (motori [i ] . enable , 0 ) ;
/ / g p i o _ s e t _ v a l u e ( m o t o r i [ i ] . b rake , 1 ) ;
motori [i ] . tacho_clicks = 0 ;
/∗ p o s t a v l j a m o i n t e r r u p t na p i n na k o j i s p o j e n t a c h o i z l a z←za b r o j e n j e rpm ∗ /
# i f n d e f NO_RPMS
ret = request_irq (gpio_to_irq (motori [i ] . tacho ) , ←speed_counter , IRQF_TRIGGER_HIGH , " S p e e d c o u n t e r f o r ←ducky " , &motori [i ] ) ;
i f (ret )
printk (KERN_WARNING " IRQ %d i s n o t f r e e \ n " , ←gpio_to_irq (motori [i ] . tacho ) ) ;
r e t u r n ret ;
# e n d i f
/∗ p o s t a v l j a m o t i m e r za r a c u n a n j e rpm i z t a c h o t i c k o v a na ←s v a k i h 1000ms ∗ /
tacho_clicks = 0 ;
setup_timer(&timer_1 , timer_func , 0 ) ;
55
ret = mod_timer(&timer_1 , jiffies + msecs_to_jiffies (SPEEDTIME←) ) ;
i f (ret )
pr_init (KERN_ERR " t i m e r f a i l e d \ n " ) ;
r e t u r n 0 ;
/∗ ∗∗ b f i n _ d u c k y _ e x i t − D e i n i t i a l i z e module
∗∗ Back o u t t h e p l a t f o r m d e v i c e & d r i v e r s t e p s . Rea l work i s i n ←
t h e
∗ p l a t f o r m remove f u n c t i o n .
∗ /
s t a t i c vo id __exit bfin_ducky_exit ( vo id )
i n t i ;
del_timer(&timer_1 ) ;
/∗ g a s e n j e modula , moramo o s l o b o d i t i z a u z e t e r e s u r s e ∗ /
f o r (i=0; i<NMOTORS ; i++)
/ / g p i o _ f r e e ( m o t o r i [ i ] . b r a k e ) ;
gpio_free (motori [i ] . direction ) ;
gpio_free (motori [i ] . enable ) ;
free_irq (gpio_to_irq (motori [i ] . tacho ) , &motori [i ] ) ;
/∗ f r e e _ i r q ( g p i o _ t o _ i r q ( ADIS_INTERRUPT ) , &i n u _ f d ) ;
c l o s e ( i n u _ f d ) ;
∗ /
platform_device_unregister (bfin_ducky_device ) ;
platform_driver_unregister(&bfin_ducky_driver ) ;
module_init (bfin_ducky_init ) ;
module_exit (bfin_ducky_exit ) ;
MODULE_AUTHOR ( " Marin Bek " ) ;
MODULE_DESCRIPTION ( " ducky k e r n e l module f o r b f i n u c l i n u x " ) ;
MODULE_LICENSE ( "GPL" ) ;
56
A.2. Komunikacija s inercijskim senzorom
/home/marin/src/adis/adis.c
# i n c l u d e < s t d i n t . h>
# i n c l u d e < u n i s t d . h>
# i n c l u d e < s t d i o . h>
# i n c l u d e < s t d l i b . h>
# i n c l u d e < g e t o p t . h>
# i n c l u d e < f c n t l . h>
# i n c l u d e < s y s / i o c t l . h>
# i n c l u d e < l i n u x / t y p e s . h>
# i n c l u d e < l i n u x / s p i / s p i d e v . h>
# i n c l u d e < l i n u x / r t c . h>
# d e f i n e ARRAY_SIZE( a ) ( s i z e o f ( a ) / s i z e o f ( ( a ) [ 0 ] ) )
# d e f i n e GRAV 2 . 5 2 2∗9 . 8 0 6 7 6 / 1 0 0 0
# d e f i n e GYRO 0.07326
# d e f i n e VOLTAGE 1 . 8 3 1 5 / 1 0 0 0
s t a t i c vo id pabort ( c o n s t c h a r ∗s )
perror (s ) ;
abort ( ) ;
s t a t i c c o n s t c h a r ∗device = " / dev / s p i d e v 0 . 1 " ;
s t a t i c uint8_t mode = 3 ;
s t a t i c uint8_t bits = 1 6 ;
s t a t i c uint32_t speed = 300000;
s t a t i c uint16_t delay = 5 0 ;
define cls ( ) printf ( " \ 0 3 3 [ 2 J " )
vo id gotoxy ( i n t x , i n t y )
printf ( "%c[%d;% df " , 0x1B , y , x ) ;
57
i n l i n e vo id read_data ( s t r u c t spi_ioc_transfer∗ xfer , i n t len , i n t ←fd )
i n t ret ;
ret = ioctl (fd , SPI_IOC_MESSAGE (len ) , xfer ) ;
i f (ret < 0)
pabort ( " c a n t send s p i msg ! \ n " ) ;
s t a t i c vo id autonull ( i n t fd )
__u16 buf ;
s t r u c t spi_ioc_transfer xfer ;
i n t ret ;
memset(&xfer , 0 , s i z e o f (xfer ) ) ;
xfer .tx_buf = (__u64 ) &buf ;
xfer .rx_buf = (__u64 ) &buf ;
xfer .len = 2 ;
xfer .speed_hz = speed ;
xfer .bits_per_word = bits ;
xfer .cs_change = 0 ;
xfer .delay_usecs = 100 ;
buf = 0x8000 + 0x3e01 ;
ret = ioctl (fd , SPI_IOC_MESSAGE ( 1 ) , &xfer ) ;
i f (ret < 0)
pabort ( " c a n t send s p i msg ! \ n " ) ;
usleep (1000000) ; /∗ 100ms v r i j e m e p o t r e b n o da se i z v r s i ←k a l i b r a c i j a ∗ /
s t a t i c vo id fact_reset ( i n t fd )
__u16 buf ;
s t r u c t spi_ioc_transfer xfer ;
i n t ret ;
memset(&xfer , 0 , s i z e o f (xfer ) ) ;
58
xfer .tx_buf = (__u64 ) &buf ;
xfer .rx_buf = (__u64 ) &buf ;
xfer .len = 2 ;
xfer .speed_hz = speed ;
xfer .bits_per_word = bits ;
xfer .cs_change = 0 ;
xfer .delay_usecs = 100 ;
buf = 0x8000 + 0x3e02 ;
ret = ioctl (fd , SPI_IOC_MESSAGE ( 1 ) , &xfer ) ;
i f (ret < 0)
pabort ( " c a n t send s p i msg ! \ n " ) ;
usleep ( 1 0 0 0 0 0 ) ; /∗ 100ms v r i j e m e p o t r e b n o da se i z v r s i ←k a l i b r a c i j a ∗ /
s t a t i c vo id test ( i n t fd )
i n t ret ;
i n t broj ;
i n t i ;
i n t rtc_fd ;
s t r u c t spi_ioc_transfer xfer [ 1 2 ] ;
__u16 buf [ 1 2 ] , ∗bp ;
autonull (fd ) ;
/∗ c i t a mo napon n a p a j a n j a ∗ /
bp = buf ;
memset (xfer , 0 , s i z e o f (xfer ) ) ;
memset (buf , 0 , s i z e o f (buf ) ) ;
f o r (i = 0 ; i < ARRAY_SIZE (xfer ) ; i++)
i f (i > 0)
xfer [i ] . rx_buf = (__u64 ) bp++;
xfer [i ] . tx_buf = (__u64 ) bp ;
xfer [i ] . len = 2 ;
xfer [i ] . speed_hz = speed ;
59
xfer [i ] . bits_per_word = bits ;
xfer [i ] . cs_change = 0 ;
xfer [i ] . delay_usecs = 3 0 ;
buf [ 0 ] = 0x0300 ;
read_data (xfer , 2 , fd ) ;
printf ( "%X\ n " , buf [ 0 ] ) ;
i f (buf [ 0 ] & (1 < <15) ) /∗ nov i p o d a t a k ∗ /
buf [ 0 ] &= 0x0fff ;
printf ( " Vcc=%.3fV \ n " , buf [ 0 ]∗VOLTAGE ) ;
rtc_fd = open ( " / dev / r t c 0 " , O_RDONLY ) ;
i f (rtc_fd == −1)
pabort ( " r t c f a i l e d t o open . \ n " ) ;
ret = ioctl (rtc_fd , RTC_UIE_ON , 0 ) ;
i f (ret == −1)
pabort ( " r t c u p d a t e i n t e r r u p t s f a i l e d . \ n " ) ;
w h i l e ( 1 )
memset (buf , 0 , s i z e o f (buf ) ) ;
buf [ 0 ] = 0x0300 ;
buf [ 1 ] = 0x0500 ; / / x a c l
buf [ 2 ] = 0x0700 ; / / y a c l
buf [ 3 ] = 0x0900 ; / / z a c l
buf [ 4 ] = 0x0b00 ; / / x gyro
buf [ 5 ] = 0x0d00 ; / / y gyro
buf [ 6 ] = 0x0f00 ; / / z gyro
read_data (xfer , 8 , fd ) ;
buf [ 0 ] &= 0x0fff ;
printf ( " %5.3fV \ t " , buf [ 0 ]∗VOLTAGE ) ;
/ / c i t am o k u t n e a k c e l e r a c i j e
f o r (i = 1 ; i < 4 ; i++)
buf [i ] &= 0x3fff ;
i f (buf [i ] & 0x2000 ) / / n e g a t i v a n ?
60
broj = −1∗((buf [i ] ^ 0x3fff ) − 1) ;
e l s e
broj = ( i n t ) buf [i ] ;
printf ( " %7.3 f \ t " , broj∗GYRO ) ;
/ / l i n e a r n e a k c e l e r a c i j e
f o r (i = 4 ; i < 7 ; i++)
buf [i ] &= 0x3fff ;
i f (buf [i ] & 0x2000 ) / / n e g a t i v a n ?
broj = −1∗((buf [i ] ^ 0x3fff ) − 1) ;
e l s e
broj = ( i n t ) buf [i ] ;
printf ( " %7.3 f \ t " , broj∗GRAV ) ;
puts ( " " ) ;
i n t main ( i n t argc , c h a r ∗argv [ ] )
i n t ret = 0 ;
i n t fd ;
fd = open (device , O_RDWR ) ;
i f (fd < 0)
pabort ( " g r e s k a p r i o t v a r a n j u " ) ;
/∗∗ s p i mode
∗ /
ret = ioctl (fd , SPI_IOC_WR_MODE , &mode ) ;
i f (ret == −1)
pabort ( " can ’ t s e t s p i mode " ) ;
ret = ioctl (fd , SPI_IOC_RD_MODE , &mode ) ;
i f (ret == −1)
pabort ( " can ’ t g e t s p i mode " ) ;
/∗
61
∗ b i t s p e r word
∗ /
ret = ioctl (fd , SPI_IOC_WR_BITS_PER_WORD , &bits ) ;
i f (ret == −1)
pabort ( " can ’ t s e t b i t s p e r word " ) ;
ret = ioctl (fd , SPI_IOC_RD_BITS_PER_WORD , &bits ) ;
i f (ret == −1)
pabort ( " can ’ t g e t b i t s p e r word " ) ;
/∗∗ max speed hz
∗ /
ret = ioctl (fd , SPI_IOC_WR_MAX_SPEED_HZ , &speed ) ;
i f (ret == −1)
pabort ( " can ’ t s e t max speed hz " ) ;
ret = ioctl (fd , SPI_IOC_RD_MAX_SPEED_HZ , &speed ) ;
i f (ret == −1)
pabort ( " can ’ t g e t max speed hz " ) ;
printf ( " s p i mode : %d \ n " , mode ) ;
printf ( " b i t s p e r word : %d \ n " , bits ) ;
printf ( "max speed : %d Hz (%d KHz) \ n " , speed , speed / 1 0 0 0 ) ;
test (fd ) ;
close (fd ) ;
r e t u r n ret ;
62
A.3. IIO komunikacija
/home/marin/src/adis_iio/adis_iio.c
# i n c l u d e < d i r e n t . h>
# i n c l u d e < f c n t l . h>
# i n c l u d e < s t d i o . h>
# i n c l u d e < e r r n o . h>
# i n c l u d e < s y s / s t a t . h>
# i n c l u d e < s y s / d i r . h>
# i n c l u d e < l i n u x / t y p e s . h>
# i n c l u d e " i i o _ u t i l s . h "
c o n s t c h a r ∗device_name = " a d i s 1 6 3 5 0 " ;
c o n s t c h a r ∗trigger_name_base = " ad i s16350−dev " ;
c o n s t i n t num_vals = 6 ;
c o n s t i n t scan_ts = 1 ;
c o n s t i n t buf_len = 128 ;
c o n s t i n t num_loops = 1000000;
i n t size_from_scanmode ( i n t num_vals , i n t timestamp )
i f (num_vals && timestamp )
r e t u r n 1 6 ;
e l s e i f (timestamp )
r e t u r n 8 ;
e l s e
r e t u r n num_vals∗2 ;
i n t main ( i n t argc , c h a r ∗∗argv )
i n t ret ;
i n t i , j , k , toread ;
FILE ∗fp_ev ;
i n t fp ;
c h a r ∗trigger_name , ∗dev_dir_name , ∗buf_dir_name ;
c h a r ∗data ;
size_t read_size ;
s t r u c t iio_event_data dat ;
63
i n t dev_num , trig_num ;
c h a r ∗buffer_access , ∗buffer_event ;
c o n s t c h a r ∗iio_dir = " / s y s / bus / i i o / d e v i c e s / " ;
i n t scan_size ;
f l o a t gain = 1 ;
/∗ Trazimo a d i s ∗ /
dev_num = find_type_by_name (device_name , " d e v i c e " ) ;
i f (dev_num < 0)
printf ( " F a i l e d t o f i n d t h e %s \ n " , device_name ) ;
ret = −ENODEV ;
go to error_ret ;
printf ( " i i o d e v i c e number b e i n g used i s %d \ n " , dev_num ) ;
asprintf(&dev_dir_name , "%s d e v i c e%d " , iio_dir , dev_num ) ;
/∗∗ k r e i r a n j e t r i g g e r a
∗ /
ret = asprintf(&trigger_name , "%s%d " , trigger_name_base , ←dev_num ) ;
i f (ret < 0)
ret = −ENOMEM ;
go to error_free_dev_dir_name ;
/∗∗ t r a z e n j e t r i g g e r a
∗ /
trig_num = find_type_by_name (trigger_name , " t r i g g e r " ) ;
i f (trig_num < 0)
printf ( " F a i l e d t o f i n d t h e %s \ n " , trigger_name ) ;
ret = −ENODEV ;
go to error_free_triggername ;
printf ( " i i o t r i g g e r number b e i n g used i s %d \ n " , trig_num ) ;
/∗∗ c i t a n j e s k a l e a k c e l e r o m e t r a
∗ /
ret = read_sysfs_float ( " a c c e l _ s c a l e " , dev_dir_name , &gain ) ;
64
i f (ret )
go to error_free_triggername ; ;
puts (dev_dir_name ) ;
printf ( "%f \ n " , gain ) ;
ret = asprintf(&buf_dir_name , "%s d e v i c e%d : b u f f e r 0 " , iio_dir , ←dev_num ) ;
i f (ret < 0)
ret = −ENOMEM ;
go to error_free_triggername ;
/∗ P o s t a v l j a m o t r i g g e r ∗ /
ret = write_sysfs_string_and_verify ( " t r i g g e r / c u r r e n t _ t r i g g e r " ,
dev_dir_name ,
trigger_name ) ;
i f (ret < 0)
printf ( " F a i l e d t o w r i t e c u r r e n t _ t r i g g e r f i l e \ n " ) ;
go to error_free_buf_dir_name ;
ret = write_sysfs_int ( " l e n g t h " , buf_dir_name , buf_len ) ;
i f (ret < 0)
go to error_free_buf_dir_name ;
ret = write_sysfs_int ( " r i n g _ e n a b l e " , buf_dir_name , 1 ) ;
i f (ret < 0)
go to error_free_buf_dir_name ;
puts (buf_dir_name ) ;
data = malloc (size_from_scanmode (num_vals , scan_ts ) ∗buf_len ) ;
i f ( !data )
ret = −ENOMEM ;
go to error_free_buf_dir_name ;
ret = asprintf(&buffer_access ,
" / dev / d e v i c e%d : b u f f e r 0 : a c c e s s 0 " ,
dev_num ) ;
i f (ret < 0)
ret = −ENOMEM ;
65
go to error_free_data ;
ret = asprintf(&buffer_event , " / dev / d e v i c e%d : b u f f e r 0 : e v e n t 0 " , ←dev_num ) ;
i f (ret < 0)
ret = −ENOMEM ;
go to error_free_data ;
/∗ n e b l o k i r a j u c e c i t a n j e ∗ /
puts (buffer_access ) ;
fp = open (buffer_access , O_RDONLY | O_NONBLOCK ) ;
i f (fp == −1)
printf ( " F a i l e d t o open %s \ n " , buffer_access ) ;
ret = −errno ;
go to error_free_buffer_event ;
fp_ev = fopen (buffer_event , " rb " ) ;
i f (fp_ev == NULL )
printf ( " F a i l e d t o open %s \ n " , buffer_event ) ;
ret = −errno ;
go to error_close_buffer_access ;
f o r (j = 0 ; j < num_loops ; j++)
read_size = fread(&dat , 1 , s i z e o f ( s t r u c t iio_event_data ) ,
fp_ev ) ;
puts ( " r e a d \ n " ) ;
s w i t c h (dat .id )
c a s e IIO_EVENT_CODE_RING_100_FULL :
toread = buf_len ;
b r e a k ;
c a s e IIO_EVENT_CODE_RING_75_FULL :
toread = buf_len ∗ 3 / 4 ;
b r e a k ;
c a s e IIO_EVENT_CODE_RING_50_FULL :
toread = buf_len / 2 ;
b r e a k ;
d e f a u l t :
printf ( " Unexpec teded e v e n t code \ n " ) ;
c o n t i n u e ;
66
read_size = read (fp ,
data ,
toread∗size_from_scanmode (num_vals , scan_ts ) ) ;
i f (read_size == −EAGAIN )
printf ( " n o t h i n g a v a i l a b l e \ n " ) ;
c o n t i n u e ;
scan_size = size_from_scanmode (num_vals , scan_ts ) ;
f o r (i = 0 ; i < read_size /scan_size ; i++)
f o r (k = 0 ; k < num_vals ; k++)
__s16 val = ∗ (__s16 ∗ ) (&data [i∗scan_size+ (k ) ∗2 ] ) ;
printf ( "%05f " , ( f l o a t )val∗gain ) ;
printf ( " %l l d \ n " ,
∗ (__s64 ∗ ) (&data [ (i + 1)
∗size_from_scanmode (num_vals ,
scan_ts )
− s i z e o f (__s64 ) ] ) ) ;
/∗ Stop ∗ /
ret = write_sysfs_int ( " r i n g _ e n a b l e " , buf_dir_name , 0 ) ;
i f (ret < 0)
go to error_close_buffer_event ;
/∗ D i s c o n n e c t . ∗ /
write_sysfs_string ( " t r i g g e r / c u r r e n t _ t r i g g e r " ,
dev_dir_name , "NULL" ) ;
error_close_buffer_event :
fclose (fp_ev ) ;
error_close_buffer_access :
close (fp ) ;
error_free_data :
free (data ) ;
error_free_buffer_access :
free (buffer_access ) ;
error_free_buffer_event :
free (buffer_event ) ;
error_free_buf_dir_name :
free (buf_dir_name ) ;
67
error_free_triggername :
free (trigger_name ) ;
error_free_dev_dir_name :
free (dev_dir_name ) ;
error_ret :
r e t u r n ret ;
68
A.4. Patch za korištenje PWM-a iz korisnickog pros-
tora
/home/marin/src/modules/pwm/bfin_simple_timer.c
/∗∗ Simple t i m e r d r i v e r
∗∗ Author : (C) 2006 by Axel Weiss ( awe@aglaia−gmbh . de )
∗∗ Thi s i s a s i m p l e char−d e v i c e i n t e r f a c e d r i v e r f o r t h e ←
b f 5 x x _ t i m e r s d r i v e r .
∗ I t p r i m a r i l y s e r v e s as an example f o r how t o use t h e ha rdware ←d r i v e r s
∗ on b l a c k f i n , b u t may a l s o be used as a s t a r t i n g p o i n t o f ←deve lopment
∗ f o r more s o p h i s t i c a t e d d r i v e r f r o n t e n d s .
∗∗ Behav iou r
∗ With t h i s d r i v e r , a d e v i c e node / dev / b f 5 x x _ t i m e r [ 0 . . . ] w i th ←major number
∗ 238 and minor number 0 . . . can be used t o a c c e s s one o f b l a c k f i n←’ s i n t e r n a l
∗ hardware t i m e r . A f t e r open ( ) , t h e t i m e r may be a c c e s s e d v i a ←i o c t l :
∗ BFIN_SIMPLE_TIMER_SET_PERIOD : s e t t i m e r p e r i o d ( i n ←m i c r o s e c o n d s )
∗ BFIN_SIMPLE_TIMER_START : s t a r t t i m e r
∗ BFIN_SIMPLE_TIMER_STOP : s t o p t i m e r
∗ BFIN_SIMPLE_TIMER_READ : r e a d t h e numbers o f p e r i o d s ( i r q−c o u n t←)
∗ Thi s d r i v e r e n a b l e s :
∗ no p h y s i c a l t i m e r o u t p u t ( OUT_DIS i s s e t )
∗ f r e e r u n n i n g from s t a r t
∗ t i m e r i n t e r r u p t , c o u n t i n g
∗ The d r i v e r opens a ( ro ) f i l e a t / p roc / b f i n _ s i m p l e _ t i m e r t h a t ←shows t h e
∗ i r q c o u n t v a l u e s f o r a l l t i m e r s .
∗∗ L i c e n s e d under t h e GPL−2 or l a t e r .
69
∗ /
# i n c l u d e < l i n u x / k e r n e l . h>
# i n c l u d e < l i n u x / i n i t . h>
# i n c l u d e < l i n u x / module . h>
# i n c l u d e < l i n u x / p r o c _ f s . h>
# i n c l u d e < l i n u x / i n t e r r u p t . h>
# i n c l u d e < l i n u x / d e v i c e . h>
# i n c l u d e <asm / g p t i m e r s . h>
# i n c l u d e <asm / portmux . h>
# i n c l u d e <asm / i r q . h>
# i n c l u d e " b f i n _ s i m p l e _ t i m e r . h "
/ / # i n c l u d e <asm / b f i n _ s i m p l e _ t i m e r . h>
# i n c l u d e <asm / b f i n−g l o b a l . h>
# d e f i n e TIMER_MAJOR 238
# d e f i n e DRV_NAME " b f i n _ s i m p l e _ t i m e r "
MODULE_AUTHOR ( " Axel Weiss <awe@aglaia−gmbh . de >" ) ;
MODULE_DESCRIPTION ( " s i m p l e t i m e r char−d e v i c e i n t e r f a c e f o r ←B l a c k f i n g p t i m e r s " ) ;
MODULE_LICENSE ( "GPL" ) ;
s t a t i c u n s i g n e d long isr_count [MAX_BLACKFIN_GPTIMERS ] ;
s t a t i c c o n s t s t r u c t
u n s i g n e d s h o r t id , bit ;
u n s i g n e d long irqbit ;
i n t irq ;
timer_code [MAX_BLACKFIN_GPTIMERS ] =
TIMER0_id , TIMER0bit , TIMER_STATUS_TIMIL0 , IRQ_TIMER0 ,
TIMER1_id , TIMER1bit , TIMER_STATUS_TIMIL1 , IRQ_TIMER1 ,
TIMER2_id , TIMER2bit , TIMER_STATUS_TIMIL2 , IRQ_TIMER2 ,
# i f (MAX_BLACKFIN_GPTIMERS > 3)
TIMER3_id , TIMER3bit , TIMER_STATUS_TIMIL3 , IRQ_TIMER3 ,
TIMER4_id , TIMER4bit , TIMER_STATUS_TIMIL4 , IRQ_TIMER4 ,
TIMER5_id , TIMER5bit , TIMER_STATUS_TIMIL5 , IRQ_TIMER5 ,
TIMER6_id , TIMER6bit , TIMER_STATUS_TIMIL6 , IRQ_TIMER6 ,
TIMER7_id , TIMER7bit , TIMER_STATUS_TIMIL7 , IRQ_TIMER7 ,
# e n d i f
# i f (MAX_BLACKFIN_GPTIMERS > 8)
TIMER8_id , TIMER8bit , TIMER_STATUS_TIMIL8 , IRQ_TIMER8 ,
TIMER9_id , TIMER9bit , TIMER_STATUS_TIMIL9 , IRQ_TIMER9 ,
TIMER10_id , TIMER10bit , TIMER_STATUS_TIMIL10 , IRQ_TIMER10 ,
70
# i f (MAX_BLACKFIN_GPTIMERS > 11)
TIMER11_id , TIMER11bit , TIMER_STATUS_TIMIL11 , IRQ_TIMER11 ,
# e n d i f
# e n d i f
;
u n s i g n e d i n t translate_minor_to_pin ( i n t minor )
s w i t c h (minor )
c a s e TIMER0_id : r e t u r n P_TMR0 ;
c a s e TIMER1_id : r e t u r n P_TMR1 ;
c a s e TIMER2_id : r e t u r n P_TMR2 ;
c a s e TIMER3_id : r e t u r n P_TMR3 ;
c a s e TIMER4_id : r e t u r n P_TMR4 ;
c a s e TIMER5_id : r e t u r n P_TMR5 ;
c a s e TIMER6_id : r e t u r n P_TMR6 ;
c a s e TIMER7_id : r e t u r n P_TMR7 ;
c a s e TIMER8_id : r e t u r n P_TMR8 ;
c a s e TIMER9_id : r e t u r n P_TMR9 ;
c a s e TIMER10_id : r e t u r n P_TMR10 ;
c a s e TIMER11_id : r e t u r n P_TMR11 ;
d e f a u l t : r e t u r n 0 ;
s t a t i c i n t timer_ioctl ( s t r u c t inode ∗inode , s t r u c t file ∗filp , ←uint cmd , u n s i g n e d long arg )
i n t minor = MINOR (inode−>i_rdev ) ;
u n s i g n e d long n ;
s w i t c h (cmd )
c a s e BFIN_SIMPLE_TIMER_SET_PERIOD :
i f (arg < 2)
r e t u r n −EFAULT ;
n = ( (get_sclk ( ) / 1000) ∗ arg ) / 1000 ;
set_gptimer_period (timer_code [minor ] . id , n ) ;
/ / s e t _ g p t i m e r _ p w i d t h ( t i m e r _ c o d e [ minor ] . id , n >> 1) ;
printk (DRV_NAME " : TIMER_SET_PERIOD : a r g=%lu , p e r i o d=%l u \ n←" ,
arg , n ) ;
b r e a k ;
c a s e BFIN_SIMPLE_TIMER_SET_WIDTH :
i f (arg < 2)
r e t u r n −EFAULT ;
71
n = ( (get_sclk ( ) / 1000) ∗ arg ) / 1000 ;
i f (n < 1)
printk ( " E r r o r 0% c y c l e n o t s u p p o r t e d ! \ n " ) ;
r e t u r n −EFAULT ;
i f (n > get_gptimer_period (timer_code [minor ] . id ) )
printk ( " Duty > p e r i o d n o t recommended ! \ n " ) ;
r e t u r n −EFAULT ;
set_gptimer_pwidth (timer_code [minor ] . id , n ) ;
printk (DRV_NAME " : TIMER_SET_WIDTH : a r g=%lu , p e r i o d=%l u \ n "←,
arg , n ) ;
b r e a k ;
c a s e BFIN_SIMPLE_TIMER_START :
set_gptimer_config (timer_code [minor ] . id , PWM_OUT | ←PERIOD_CNT | PULSE_HI ) ;
enable_gptimers (timer_code [minor ] . bit ) ;
b r e a k ;
c a s e BFIN_SIMPLE_TIMER_STOP :
disable_gptimers (timer_code [minor ] . bit ) ;
b r e a k ;
/∗ c a s e BFIN_SIMPLE_TIMER_READ :
∗ ( ( u n s i g n e d long ∗ ) a r g ) = i s r _ c o u n t [ minor ] ;
b r e a k ; ∗ /
d e f a u l t :
r e t u r n −EINVAL ;
r e t u r n 0 ;
s t a t i c irqreturn_t timer_isr ( i n t irq , vo id ∗dev_id )
i n t minor = ( i n t )dev_id ;
# i f (MAX_BLACKFIN_GPTIMERS > 8)
i n t octet = BFIN_TIMER_OCTET (minor ) ;
# e l s e
i n t octet = 0 ;
# e n d i f
u n s i g n e d long state = get_gptimer_status (octet ) ;
i f (state & timer_code [minor ] . irqbit )
set_gptimer_status (octet , timer_code [minor ] . irqbit ) ;
72
++isr_count [minor ] ;
r e t u r n IRQ_HANDLED ;
s t a t i c i n t timer_open ( s t r u c t inode ∗inode , s t r u c t file ∗filp )
i n t minor = MINOR (inode−>i_rdev ) ;
i n t err = 0 ;
i f (minor >= MAX_BLACKFIN_GPTIMERS )
r e t u r n −ENODEV ;
/∗ e r r = r e q u e s t _ i r q ( t i m e r _ c o d e [ minor ] . i r q , t i m e r _ i s r , ←IRQF_DISABLED , DRV_NAME, ( vo id ∗ ) minor ) ;
i f ( e r r < 0 )
p r i n t k (KERN_ERR " r e q u e s t _ i r q (%d ) f a i l e d \ n " , t i m e r _ c o d e [←minor ] . i r q ) ;
r e t u r n e r r ;
∗ /
err = peripheral_request (translate_minor_to_pin (minor ) , ←DRV_NAME ) ;
i f (err )
printk (KERN_ERR " Timer p i n r e q u e s t f a i l e d ! \ n " ) ;
peripheral_free (translate_minor_to_pin (minor ) ) ;
r e t u r n err ;
printk ( " t i m e r %d pwm opened \ n " , minor ) ;
/ / s e t _ g p t i m e r _ c o n f i g ( t i m e r _ c o d e [ minor ] . id , OUT_DIS | PWM_OUT |←PERIOD_CNT | IRQ_ENA) ;
/ / p r_debug (DRV_NAME " : d e v i c e (%d ) opened \ n " , minor ) ;
r e t u r n 0 ;
s t a t i c i n t timer_close ( s t r u c t inode ∗inode , s t r u c t file ∗filp )
i n t minor = MINOR (inode−>i_rdev ) ;
disable_gptimers (timer_code [minor ] . bit ) ;
/ / f r e e _ i r q ( t i m e r _ c o d e [ minor ] . i r q , ( vo id ∗ ) minor ) ;
/ / p r_debug (DRV_NAME " : d e v i c e (%d ) c l o s e d \ n " , minor ) ;
peripheral_free (translate_minor_to_pin (minor ) ) ;
r e t u r n 0 ;
73
s t a t i c i n t timer_read_proc ( c h a r ∗buf , c h a r ∗∗start , off_t offset , ←i n t cnt , i n t ∗eof , vo id ∗data )
i n t i , ret = 0 ;
f o r (i = 0 ; i < MAX_BLACKFIN_GPTIMERS ; ++i )
ret += sprintf (buf + ret , " t i m e r %2d i s r c o u n t : %l u \ n " , i ,←isr_count [i ] ) ;
r e t u r n ret ;
s t a t i c ssize_t
timer_status_show ( s t r u c t c l a s s ∗timer_class , s t r u c t ←class_attribute ∗attr ,
c h a r ∗buf )
c h a r ∗p ;
u n s i g n e d s h o r t i ;
p = buf ;
f o r (i = 0 ; i < MAX_BLACKFIN_GPTIMERS ; ++i )
p += sprintf (p , " t i m e r %2d i s r c o u n t : %l u \ n " , i , isr_count←[i ] ) ;
r e t u r n p − buf ;
s t a t i c s t r u c t file_operations fops =
.owner = THIS_MODULE ,
.ioctl = timer_ioctl ,
.open = timer_open ,
.release = timer_close ,
;
s t a t i c s t r u c t proc_dir_entry ∗timer_dir_entry ;
s t a t i c s t r u c t c l a s s ∗timer_class ;
s t a t i c CLASS_ATTR (status , S_IRUGO , &timer_status_show , NULL ) ;
s t a t i c i n t __init timer_initialize ( vo id )
i n t minor ;
i n t err ;
74
err = register_chrdev (TIMER_MAJOR , DRV_NAME , &fops ) ;
i f (err < 0)
pr_debug (DRV_NAME " : c o u l d n o t r e g i s t e r d e v i c e %s \ n " , ←DRV_NAME ) ;
r e t u r n err ;
timer_dir_entry = create_proc_entry (DRV_NAME , 0444 , NULL ) ;
i f (timer_dir_entry )
timer_dir_entry−>read_proc = &timer_read_proc ;
timer_class = class_create (THIS_MODULE , " t i m e r " ) ;
err = class_create_file (timer_class , &class_attr_status ) ;
i f (err )
remove_proc_entry (DRV_NAME , NULL ) ;
unregister_chrdev (TIMER_MAJOR , DRV_NAME ) ;
r e t u r n err ;
minor = 0 ;
# i f d e f CONFIG_TICK_SOURCE_SYSTMR0
/∗ g p t i m e r 0 i s used t o g e n e r a t e t h e t i c k i n t e r r u p t ∗ /
++minor ;
# e n d i f
f o r (minor = 0 ; minor < MAX_BLACKFIN_GPTIMERS ; minor++)
device_create (timer_class , NULL , MKDEV (TIMER_MAJOR , minor )←,
NULL , " t i m e r%d " , minor ) ;
pr_debug (DRV_NAME " : module l o a d e d \ n " ) ;
r e t u r n 0 ;
module_init (timer_initialize ) ;
s t a t i c vo id __exit timer_cleanup ( vo id )
remove_proc_entry (DRV_NAME , NULL ) ;
unregister_chrdev (TIMER_MAJOR , DRV_NAME ) ;
pr_debug (DRV_NAME " : module u n l o a d e d \ n " ) ;
module_exit (timer_cleanup ) ;
75