Matlab függvény: Logger Lite olvasó kényszerrezgéshez

A Fizipedia wikiből
A lap korábbi változatát látod, amilyen Balogh (vitalap | szerkesztései) 2022. október 26., 11:07-kor történt szerkesztése után volt.

Segítség a függvény elkészítéséhez

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, pl. 5 soros fejléc esetén textscan(fid,"%f %f %f",'Delimiter','\t','HeaderLines',5,)

A megfelelő függvény egy lehetséges megvalósítása

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. 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].
  • 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 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=[];
   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. 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.
               %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};
       signal_drive=temp{5};
       pos=temp{2}(find(temp{2}~=-Inf));
       t=temp{1}(find(temp{2}~=-Inf));
               %Ha adtunk meg start és stop értéket, akkor kivágja a kettő közötti tartományt.
       if(stop>start)
           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 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 5V-hoz közeli értékeket 5V-ra állítjuk, így az esetleges zaj nem fog zavarni a numerikus deriváltban.
       signal_drive(find(signal_drive>=4.95))=5;
               %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;
   catch
       if(isempty(drive_fq))
           disp("Hiba az optikai jeladó jelének feldolgozásában!")
           return
       end
           disp("Hiba a futtatásban!")
       return
   end