„Matlab függvény: Logger Lite olvasó kényszerrezgéshez” változatai közötti eltérés
(Új oldal, tartalma: „==A függvény Matlab kódja== function [t pos pos0 t_drive signal_drive drive_fq]=read_sin_dr(file,start,stop) arguments file (1,1) string start …”) |
|||
(egy szerkesztő 13 közbeeső változata nincs mutatva) | |||
1. sor: | 1. sor: | ||
− | == | + | ==Segítség egy egyszerű függvény elkészítéséhez== |
− | + | Ebben a részben szövegesen nyújtunk segítséget a függvény elkészítéséhez. Gyakorlásként célszerű saját ötlet, vagy a lenti segítség alapján elkészíteni a megfelelő függvényt. Ha ez nem kivitelezhető (túlmutat a gyakorlat idején, nincs megfelelő Matlab tapasztalat), akkor a következő fejezetben egy konkrét példát talál a függvényre, melyet használni is tud a mérés során. | |
− | + | '''FIGYELEM''' A lenti példa függvény bonyolultabb, mint a gyakorlat elvégzéséhez szükséges funkcionalitású függvény. A saját készítésű függvény ettől lehet sokkal egyszerűbb. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Első lépésként vizsgálja meg az adatfájl struktúráját és határozza meg milyen formátumban szerepelnek benne az adatok (oszlopok száma, oszlopok azonosítása, elválasztó karakter, fejlécsorok száma)! | |
− | + | A beolvasáshoz a ''textscan()'' függvényt célszerű használni (a függvényről bővebb információkat a Matlab help-ben talál, mely megnyílik, ha beírja a ''doc textscan'' parancsot a Command Window-ba) | |
+ | *A függvény első paramétere a fájl azonosítója, melyet a fájl megnyitására szolgáló ''fopen()'' függvény ad vissza. | ||
+ | *Második paraméterként az adatok formátumát kell megadni egy stringként pl. három double értéket tartalmazó oszlop esetén az alábbi formátumban: ''"%f %f %f"'' | ||
+ | *A ''Delimiter'' tulajdonság beállításával határozhatjuk meg az elválasztó karaktert. Példa tabulátor elválaszto karakter esetére: ''textscan(fid,"%f %f %f",'Delimiter','\t')''. | ||
+ | *A ''HeaderLines'' tulajdonság beállításával határizhatjuk meg a fejlécsorok számát. Példa 5 soros fejléc esetére: ''textscan(fid,"%f %f %f",'Delimiter','\t','HeaderLines',5,)''. | ||
− | + | A fentiekkel az alapvető beolvasást el tudjuk végezni, azonban ha alaposabban megvizsgáljuk az adatokat, látható, hogy amennyiben a GoLink szenzort is csatlakoztatjuk és az optikai jeladó jelét is mérjük pl. 100Hz-el, akkor a GoMotion jelét túlmintavételezzük (max 25Hz-es mintavételezésre képes). A Logger Lite azokat a sorokat, amelyeknél nem tudott adatot rögzíteni a GoMotion szenzor, egy szóközzel tölti fel. Ezt a beolvasáskor kezelnünk kell. | |
− | + | *A ''TreatAsEmpty'' paraméterrel álíthatjuk be, hogy a szóközt üres értékként kezelje, majd az ''EmptyValue'' paraméterrel azt is be tudjuk állítani, hogy az üres értékek helyére milyen értéket írjon a textscan() függvény. Ennek az értéknek célszerű valami jól felismerhető értéket választani, mert később erre szereténk szűrni (pl. végtelen, negatív végtelen, stb). Folytatva a fenti függvényt, példa az üres sorok kezelésére és feltöltésére negatív végtelennel: ''textscan(fid,"%f %f %f",'Delimiter','\t','HeaderLines',5,'TreatAsEmpty',{' '},'EmptyValue',-Inf)''. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | A ''textscan'' függvény kimenetként egy cell típusú változót ad vissza, melynek egyes elemei a beolvasott oszlopok. A továbbiakban az időjelre és a GoMotion pozíciójának értékeire lesz szükség, ezeket célszerű kimásolni 1-1 vektorba. Ha túlmintavételeztük a GoMotion szenzort, akkor az üres értékeket még kezelnünk kell. Ehhez célszerű a ''find()'' függvényt használni! | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | %A pozíció nullontját kiszámolja egyszerű átlagolással és levonja, így | + | ==A megfelelő függvény egy lehetséges megvalósítása kis extrával== |
− | + | Az alábbi függvénnyel megvalósítható a GoMotion jelének beolvasása, sőt extraként a meghajtójel frekvenciáját is kiszámolja, ha csatlakoztatva van a GoLink szenzor. A függvény bemeneteként meg kell adni a Logger Lite által kimentett fájl elérési útját és opcionális paraméterként megadható egy kezdeti és egy végső időpontot (másodpercben). A függvény a két időpont közötti adatokat fogja betölteni. | |
− | pos0=mean(pos); | + | Fontos, hogy a GoMotion legyen az 1-es számú szenzor, így a pozíciójel a kimentett fájl második oszlopába kerül. Ha az optikai szenzor jelét mérő GoLink nincs csatlakoztatva, akkor azt a függvény jelzi, így a meghajtásra vonatkozó értékeket nem számolja ki, de a GoMotion pozíciójelét így is ki tudja számolni. |
− | pos=pos-pos0; | + | A függvény a következő kimeneteket adja vissza: |
− | %Meghajtás frekvenciájának meghatározása: | + | * t - a GoMotion szenzor mintavételezéséhez tartozó időpillanatok [s] |
− | %Először kisimítjuk a jelet, az | + | * pos - A GoMotion szenzor által mért pozíció (nullára centrálva) [m] |
− | + | * pos0 - A GoMotion által mért pozíció átlaga, azaz a rúd nyugalmi helyzete (a tényleges pozíció a pos és pos0 összege) [m] | |
− | signal_drive(find(signal_drive>= | + | * t_drive - A GoLink szenzor mintavételezési időpontjai [s] |
− | %Vesszük a deriváltat és meghatározzuk az előjelét minden pontra. Azokat az | + | * signal_drive - A GoLink szenzor jele [V]. |
− | + | * sin_drive - A függvény által számolt elméleti szinuszos meghajtójel normált amplitúdóval. | |
− | sgn_diff=sign(diff(signal_drive)); | + | * drive_fq - A meghajtójel függvény által számolt értéke [Hz] |
− | %Először megkeressük a negatív helyeket, majd egy for ciklussal megnézzük | + | ===A függvény Matlab kódja=== |
− | + | function [t pos pos0 t_drive signal_drive sin_drive drive_fq]=read_sin_dr(file,start,stop) | |
− | + | arguments | |
− | posn=find(sgn_diff==-1); | + | file (1,1) string |
− | posp=[]; | + | start (1,1) {mustBeNumeric, mustBeFinite} =0 |
− | for i=1:length(posn) | + | stop (1,1) {mustBeNumeric} = Inf |
− | if(sgn_diff(posn(i)+1)==1) | + | end |
− | posp(end+1)=posn(i)+1; | + | %Fontos, hogy a GoLink és a GoMotion is csatlakoztatva legyen és a megfelelő legyen a sorrendjük! GoMotion poziítiója legyen a 2. oszlop! |
− | end | + | t=[]; |
− | end | + | pos=[]; |
− | %Megszámoljuk hány csúcs volt összesen és az utolsó, valamint az első | + | pos0=[]; |
− | + | t_drive=[]; | |
− | + | signal_drive=[]; | |
− | + | sin_drive=[]; | |
− | Nump=length(posp); | + | drive_fq=[]; |
− | DT=t_drive(posp(end))-t_drive(posp(1)); | + | try |
− | dt=DT/(Nump-1); | + | %Fájl megnyitása |
− | drive_fq=1/dt; | + | fid=fopen(file); |
− | + | if(fid==-1) | |
− | if(isempty(drive_fq)) | + | disp("Hiba a fájl megnyitásakor!") |
− | + | return | |
− | + | end | |
+ | %Beolvasás a fájlból: | ||
+ | %A Logger Lite által kimentett txt 7 fejlécsort tartalmaz, ezt kezeljük a -- 'HeaderLines',7 -- beállítással, utána 5 oszlopban tabulátorral elválasztva jönnek az adatok, a formátum "%f %f %f %f %f" (double értékeket olvasunk be) és az elválasztó karaktert a -- 'Delimiter','\t' -- állítja be. | ||
+ | %A túlmintavételezés miatt a GoMotion szenzor jelében csak minden negyedik sorban szerepel érték, a beolvasásnál ezt kezelni kell. A kimaradó értékek helyett szóköz szerepel, a beolvasófüggvényben ezt üres értékként kezeljük, amit a -- 'TreatAsEmpty',{' '} -- állít be. Utána az üres értékeket negatív végtelenre állítjuk, mert erre könnyű szűrni, ezt a -- 'EmptyValue',-Inf -- beállítás oldja meg. | ||
+ | temp=textscan(fid,"%f %f %f %f %f",'Delimiter','\t','HeaderLines',7,'TreatAsEmpty',{' '},'EmptyValue',-Inf); | ||
+ | %A beolvasás egy cell változót ad vissza, ebből kivesszük az értékekek. Az első oszlop az idő, a második oszlop a GoMotion jele, az 5. oszlop a GoLink jele. | ||
+ | t_drive=temp{1}; | ||
+ | signal_drive=temp{5}; | ||
+ | t=temp{1}; | ||
+ | pos=temp{2}; | ||
+ | %Ha adtunk meg start és stop értéket, akkor kivágja a kettő közötti tartományt. | ||
+ | if(stop>start) | ||
+ | temp2=temp{2}(find(t_drive>=start&t_drive<=stop)); %Ezt a változót majd az elméleti meghajtójel levágásánál használjuk | ||
+ | signal_drive=signal_drive(find(t_drive>=start&t_drive<=stop)); | ||
+ | t_drive=t_drive(find(t_drive>=start&t_drive<=stop)); | ||
+ | pos=pos(find(t>=start&t<=stop)); | ||
+ | t=t(find(t>=start&t<=stop)); | ||
+ | end | ||
+ | %A GoMotion jeléből csak azokat a sorokat szeretnénk a végső jelben látni, ahol ténylegesen van érték. Ezek a nem -Inf-el egyenlő sorok, ezeket keressük meg a find() függvénnyel és csak ezeket adjuk át a pos változónak. | ||
+ | %Utána az időjelnél hasonlóan járunk el, csak azokat az időpontokat adjuk át, amelyeknél a pozíciónak értelmes értéke van. | ||
+ | t=t(find(pos~=-Inf)); | ||
+ | pos=pos(find(pos~=-Inf)); | ||
+ | %A pozíció nullontját kiszámolja egyszerű átlagolással és levonja, így egyszerűbb a későbbi illesztés | ||
+ | pos0=mean(pos); | ||
+ | pos=pos-pos0; | ||
+ | %Meghajtás frekvenciájának meghatározása: | ||
+ | %Először kisimítjuk a jelet, az 3V-hoz közeli értékeket 3V-ra állítjuk, így az esetleges zaj nem fog zavarni a numerikus deriváltban. | ||
+ | signal_drive(find(signal_drive>=2.95))=3; | ||
+ | %Vesszük a deriváltat és meghatározzuk az előjelét minden pontra. Azokat az pozíciókat keressük majd, ahol a derivált előjelet vált. | ||
+ | sgn_diff=sign(diff(signal_drive)); | ||
+ | %Először megkeressük a negatív helyeket, majd egy for ciklussal megnézzük minden negatív pont utáni pontban az előjelet és ahol pozitív, ott volt egy csúcs | ||
+ | posn=find(sgn_diff==-1); | ||
+ | posp=[]; | ||
+ | for i=1:length(posn) | ||
+ | if(sgn_diff(posn(i)+1)==1) | ||
+ | posp(end+1)=posn(i)+1; | ||
+ | end | ||
+ | end | ||
+ | %Megszámoljuk hány csúcs volt összesen és az utolsó, valamint az első pozíciójának különbségéből tudjuk az időt, ezt el kell osztani a periódusok (csúcs-1) számával és megvan a preiódusidő, ebből pedig a frekvencia. | ||
+ | Nump=length(posp); | ||
+ | DT=t_drive(posp(end))-t_drive(posp(1)); | ||
+ | dt=DT/(Nump-1); | ||
+ | drive_fq=1/dt; | ||
+ | %Elkészíti az elméleti meghajtójelet | ||
+ | sin_drive=cos(2*pi*drive_fq*(t_drive-t_drive(posp(1)))+pi); | ||
+ | sin_drive=sin_drive(find(temp2~=-Inf)); | ||
+ | catch | ||
+ | if(isempty(drive_fq)) | ||
+ | disp("Hiba az optikai jeladó jelének feldolgozásában!") | ||
+ | return | ||
+ | end | ||
+ | disp("Hiba a futtatásban!") | ||
+ | return | ||
end | end | ||
− | |||
− | |||
− |
A lap jelenlegi, 2024. szeptember 11., 12:56-kori változata
Segítség egy egyszerű függvény elkészítéséhez
Ebben a részben szövegesen nyújtunk segítséget a függvény elkészítéséhez. Gyakorlásként célszerű saját ötlet, vagy a lenti segítség alapján elkészíteni a megfelelő függvényt. Ha ez nem kivitelezhető (túlmutat a gyakorlat idején, nincs megfelelő Matlab tapasztalat), akkor a következő fejezetben egy konkrét példát talál a függvényre, melyet használni is tud a mérés során. FIGYELEM A lenti példa függvény bonyolultabb, mint a gyakorlat elvégzéséhez szükséges funkcionalitású függvény. A saját készítésű függvény ettől lehet sokkal egyszerűbb.
Első lépésként vizsgálja meg az adatfájl struktúráját és határozza meg milyen formátumban szerepelnek benne az adatok (oszlopok száma, oszlopok azonosítása, elválasztó karakter, fejlécsorok száma)! A beolvasáshoz a textscan() függvényt célszerű használni (a függvényről bővebb információkat a Matlab help-ben talál, mely megnyílik, ha beírja a doc textscan parancsot a Command Window-ba)
- A függvény első paramétere a fájl azonosítója, melyet a fájl megnyitására szolgáló fopen() függvény ad vissza.
- Második paraméterként az adatok formátumát kell megadni egy stringként pl. három double értéket tartalmazó oszlop esetén az alábbi formátumban: "%f %f %f"
- A Delimiter tulajdonság beállításával határozhatjuk meg az elválasztó karaktert. Példa tabulátor elválaszto karakter esetére: textscan(fid,"%f %f %f",'Delimiter','\t').
- A HeaderLines tulajdonság beállításával határizhatjuk meg a fejlécsorok számát. Példa 5 soros fejléc esetére: textscan(fid,"%f %f %f",'Delimiter','\t','HeaderLines',5,).
A fentiekkel az alapvető beolvasást el tudjuk végezni, azonban ha alaposabban megvizsgáljuk az adatokat, látható, hogy amennyiben a GoLink szenzort is csatlakoztatjuk és az optikai jeladó jelét is mérjük pl. 100Hz-el, akkor a GoMotion jelét túlmintavételezzük (max 25Hz-es mintavételezésre képes). A Logger Lite azokat a sorokat, amelyeknél nem tudott adatot rögzíteni a GoMotion szenzor, egy szóközzel tölti fel. Ezt a beolvasáskor kezelnünk kell.
- A TreatAsEmpty paraméterrel álíthatjuk be, hogy a szóközt üres értékként kezelje, majd az EmptyValue paraméterrel azt is be tudjuk állítani, hogy az üres értékek helyére milyen értéket írjon a textscan() függvény. Ennek az értéknek célszerű valami jól felismerhető értéket választani, mert később erre szereténk szűrni (pl. végtelen, negatív végtelen, stb). Folytatva a fenti függvényt, példa az üres sorok kezelésére és feltöltésére negatív végtelennel: textscan(fid,"%f %f %f",'Delimiter','\t','HeaderLines',5,'TreatAsEmpty',{' '},'EmptyValue',-Inf).
A textscan függvény kimenetként egy cell típusú változót ad vissza, melynek egyes elemei a beolvasott oszlopok. A továbbiakban az időjelre és a GoMotion pozíciójának értékeire lesz szükség, ezeket célszerű kimásolni 1-1 vektorba. Ha túlmintavételeztük a GoMotion szenzort, akkor az üres értékeket még kezelnünk kell. Ehhez célszerű a find() függvényt használni!
A megfelelő függvény egy lehetséges megvalósítása kis extrával
Az alábbi függvénnyel megvalósítható a GoMotion jelének beolvasása, sőt extraként a meghajtójel frekvenciáját is kiszámolja, ha csatlakoztatva van a GoLink szenzor. A függvény bemeneteként meg kell adni a Logger Lite által kimentett fájl elérési útját és opcionális paraméterként megadható egy kezdeti és egy végső időpontot (másodpercben). A függvény a két időpont közötti adatokat fogja betölteni. Fontos, hogy a GoMotion legyen az 1-es számú szenzor, így a pozíciójel a kimentett fájl második oszlopába kerül. Ha az optikai szenzor jelét mérő GoLink nincs csatlakoztatva, akkor azt a függvény jelzi, így a meghajtásra vonatkozó értékeket nem számolja ki, de a GoMotion pozíciójelét így is ki tudja számolni. A függvény a következő kimeneteket adja vissza:
- t - a GoMotion szenzor mintavételezéséhez tartozó időpillanatok [s]
- pos - A GoMotion szenzor által mért pozíció (nullára centrálva) [m]
- pos0 - A GoMotion által mért pozíció átlaga, azaz a rúd nyugalmi helyzete (a tényleges pozíció a pos és pos0 összege) [m]
- t_drive - A GoLink szenzor mintavételezési időpontjai [s]
- signal_drive - A GoLink szenzor jele [V].
- sin_drive - A függvény által számolt elméleti szinuszos meghajtójel normált amplitúdóval.
- drive_fq - A meghajtójel függvény által számolt értéke [Hz]
A függvény Matlab kódja
function [t pos pos0 t_drive signal_drive sin_drive drive_fq]=read_sin_dr(file,start,stop) arguments file (1,1) string start (1,1) {mustBeNumeric, mustBeFinite} =0 stop (1,1) {mustBeNumeric} = Inf end %Fontos, hogy a GoLink és a GoMotion is csatlakoztatva legyen és a megfelelő legyen a sorrendjük! GoMotion poziítiója legyen a 2. oszlop! t=[]; pos=[]; pos0=[]; t_drive=[]; signal_drive=[]; sin_drive=[]; drive_fq=[]; try %Fájl megnyitása fid=fopen(file); if(fid==-1) disp("Hiba a fájl megnyitásakor!") return end %Beolvasás a fájlból: %A Logger Lite által kimentett txt 7 fejlécsort tartalmaz, ezt kezeljük a -- 'HeaderLines',7 -- beállítással, utána 5 oszlopban tabulátorral elválasztva jönnek az adatok, a formátum "%f %f %f %f %f" (double értékeket olvasunk be) és az elválasztó karaktert a -- 'Delimiter','\t' -- állítja be. %A túlmintavételezés miatt a GoMotion szenzor jelében csak minden negyedik sorban szerepel érték, a beolvasásnál ezt kezelni kell. A kimaradó értékek helyett szóköz szerepel, a beolvasófüggvényben ezt üres értékként kezeljük, amit a -- 'TreatAsEmpty',{' '} -- állít be. Utána az üres értékeket negatív végtelenre állítjuk, mert erre könnyű szűrni, ezt a -- 'EmptyValue',-Inf -- beállítás oldja meg. temp=textscan(fid,"%f %f %f %f %f",'Delimiter','\t','HeaderLines',7,'TreatAsEmpty',{' '},'EmptyValue',-Inf); %A beolvasás egy cell változót ad vissza, ebből kivesszük az értékekek. Az első oszlop az idő, a második oszlop a GoMotion jele, az 5. oszlop a GoLink jele. t_drive=temp{1}; signal_drive=temp{5}; t=temp{1}; pos=temp{2}; %Ha adtunk meg start és stop értéket, akkor kivágja a kettő közötti tartományt. if(stop>start) temp2=temp{2}(find(t_drive>=start&t_drive<=stop)); %Ezt a változót majd az elméleti meghajtójel levágásánál használjuk signal_drive=signal_drive(find(t_drive>=start&t_drive<=stop)); t_drive=t_drive(find(t_drive>=start&t_drive<=stop)); pos=pos(find(t>=start&t<=stop)); t=t(find(t>=start&t<=stop)); end %A GoMotion jeléből csak azokat a sorokat szeretnénk a végső jelben látni, ahol ténylegesen van érték. Ezek a nem -Inf-el egyenlő sorok, ezeket keressük meg a find() függvénnyel és csak ezeket adjuk át a pos változónak. %Utána az időjelnél hasonlóan járunk el, csak azokat az időpontokat adjuk át, amelyeknél a pozíciónak értelmes értéke van. t=t(find(pos~=-Inf)); pos=pos(find(pos~=-Inf)); %A pozíció nullontját kiszámolja egyszerű átlagolással és levonja, így egyszerűbb a későbbi illesztés pos0=mean(pos); pos=pos-pos0; %Meghajtás frekvenciájának meghatározása: %Először kisimítjuk a jelet, az 3V-hoz közeli értékeket 3V-ra állítjuk, így az esetleges zaj nem fog zavarni a numerikus deriváltban. signal_drive(find(signal_drive>=2.95))=3; %Vesszük a deriváltat és meghatározzuk az előjelét minden pontra. Azokat az pozíciókat keressük majd, ahol a derivált előjelet vált. sgn_diff=sign(diff(signal_drive)); %Először megkeressük a negatív helyeket, majd egy for ciklussal megnézzük minden negatív pont utáni pontban az előjelet és ahol pozitív, ott volt egy csúcs posn=find(sgn_diff==-1); posp=[]; for i=1:length(posn) if(sgn_diff(posn(i)+1)==1) posp(end+1)=posn(i)+1; end end %Megszámoljuk hány csúcs volt összesen és az utolsó, valamint az első pozíciójának különbségéből tudjuk az időt, ezt el kell osztani a periódusok (csúcs-1) számával és megvan a preiódusidő, ebből pedig a frekvencia. Nump=length(posp); DT=t_drive(posp(end))-t_drive(posp(1)); dt=DT/(Nump-1); drive_fq=1/dt; %Elkészíti az elméleti meghajtójelet sin_drive=cos(2*pi*drive_fq*(t_drive-t_drive(posp(1)))+pi); sin_drive=sin_drive(find(temp2~=-Inf)); catch if(isempty(drive_fq)) disp("Hiba az optikai jeladó jelének feldolgozásában!") return end disp("Hiba a futtatásban!") return end