„Matlab függvény: Logger Lite olvasó kényszerrezgéshez” változatai közötti eltérés

A Fizipedia wikiből
 
(egy szerkesztő 9 közbeeső változata nincs mutatva)
1. sor: 1. sor:
==Segítség a függvény elkészítéséhez==
+
==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)!
 
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 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.
 
*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"''
 
*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 ''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, pl. 5 soros fejléc esetén ''textscan(fid,"%f %f %f",'Delimiter','\t','HeaderLines',5,)''
+
*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==
+
==A megfelelő függvény egy lehetséges megvalósítása kis extrával==
Az alábbi 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.
+
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.
 
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:
 
A függvény a következő kimeneteket adja vissza:
16. sor: 24. sor:
 
* t_drive - A GoLink szenzor mintavételezési időpontjai [s]
 
* t_drive - A GoLink szenzor mintavételezési időpontjai [s]
 
* signal_drive - A GoLink szenzor jele [V].
 
* 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]  
 
* drive_fq - A meghajtójel függvény által számolt értéke [Hz]  
 
===A függvény Matlab kódja===
 
===A függvény Matlab kódja===
    function [t pos pos0 t_drive signal_drive drive_fq]=read_sin_dr(file,start,stop)
+
  function [t pos pos0 t_drive signal_drive sin_drive drive_fq]=read_sin_dr(file,start,stop)
 
         arguments
 
         arguments
 
             file (1,1) string
 
             file (1,1) string
30. sor: 39. sor:
 
     t_drive=[];
 
     t_drive=[];
 
     signal_drive=[];
 
     signal_drive=[];
 +
    sin_drive=[];
 
     drive_fq=[];
 
     drive_fq=[];
 
     try
 
     try
42. sor: 52. sor:
 
                 %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.
 
                 %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);
 
     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. A második oszlop a GoMotion jele, ebből csak azokat 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.
+
                 %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.
                %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_drive=temp{1};
 
         t_drive=temp{1};
 
         signal_drive=temp{5};
 
         signal_drive=temp{5};
         pos=temp{2}(find(temp{2}~=-Inf));
+
         t=temp{1};
         t=temp{1}(find(temp{2}~=-Inf));
+
         pos=temp{2};
 
                 %Ha adtunk meg start és stop értéket, akkor kivágja a kettő közötti tartományt.
 
                 %Ha adtunk meg start és stop értéket, akkor kivágja a kettő közötti tartományt.
 
         if(stop>start)
 
         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));
 
             signal_drive=signal_drive(find(t_drive>=start&t_drive<=stop));
 
             t_drive=t_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));
 
             pos=pos(find(t>=start&t<=stop));
             t=t(find(t>=start&t<=stop));
+
             t=t(find(t>=start&t<=stop));  
 
         end
 
         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
 
                 %A pozíció nullontját kiszámolja egyszerű átlagolással és levonja, így egyszerűbb a későbbi illesztés
 
         pos0=mean(pos);
 
         pos0=mean(pos);
 
         pos=pos-pos0;
 
         pos=pos-pos0;
 
                 %Meghajtás frekvenciájának meghatározása:
 
                 %Meghajtás frekvenciájának meghatározása:
                 %Először kisimítjuk a jelet, az 5V-hoz közeli értékeket 5V-ra állítjuk, így az esetleges zaj nem fog zavarni a numerikus deriváltban.
+
                 %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>=4.95))=5;
+
         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.
 
                 %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));
 
         sgn_diff=sign(diff(signal_drive));
76. sor: 90. sor:
 
         dt=DT/(Nump-1);
 
         dt=DT/(Nump-1);
 
         drive_fq=1/dt;
 
         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
 
     catch
 
         if(isempty(drive_fq))
 
         if(isempty(drive_fq))

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