Ortalama bir zaman aralığındaki alınan verilerin toplamının veri sayısına bölünmesi ile hesaplanır. Hareketli ortalama ise zaman aralığının sürekli kaydırılması ile hesaplanır. Yani normal ortalamada her veride ortalama tekrar hesaplanırken, hareketli ortalamada en eski veri ortalamadan atılır ve yeni veri ortalamaya alınır. hareketli ortalama, ortalamaya girecek eleman sayısı ve 'de değerler olmak üzere, hareketli ortalama şu şekilde yazılabilir:
Bölme işlemi diğer işlemlere göre daha yavaş hesaplandığından dolayı, eleman sayısı 'nin kuvveti olarak seçilerek bölme işlemi bitsel kaydırma işlemine dönüştürülebilir.
Donanımsal tasarım aşağıdaki gibi gösterilebilir:
Tasarımı daha kolay anlaşılabilir hale getirmek için, tasarımı modüller sayesinde yapalım. Her bir modül aşağıdaki gibi olsun.
Bu modülün VHDL kodu aşağıdadır:
--Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity MovingAverageModule is generic(DataLength : integer := 12; --Veri uzunluğu SumLength : integer := 17); --Toplam verisinin uzunluğu port(Clk, Reset : in std_logic; --Clock ve reset girişi D : in std_logic_vector(DataLength - 1 downto 0); --Veri girişi Q : out std_logic_vector(DataLength - 1 downto 0); --Veri çıkışı SumIn : in std_logic_vector(SumLength - 1 downto 0); --Toplam verisi girişi SumOut : out std_logic_vector(SumLength - 1 downto 0)); --Toplam verisi çıkışı end MovingAverageModule; architecture Behavioral of MovingAverageModule is --Q sinyali signal QSignal : std_logic_vector(DataLength - 1 downto 0); begin --Flip-Flop processi process(Clk, Reset) begin --Eğer Reset sinyali '1' ise flip-flop'u resetle if Reset = '1' then QSignal <= (others => '0'); --Reset '1' değilse, clock sinyalinin yükselen kenarı ile --D sinyalindeki veriyi QSignal sinyaline ata elsif rising_edge(Clk) then QSignal <= D; end if; end process; --QSignal sinyalini Q sinyaline bağla Q <= QSignal; --SumIn ve QSignal sinyallerini topla ve SumOut sinyaline gönder SumOut <= std_logic_vector(unsigned(SumIn) + unsigned(QSignal)); end Behavioral;
Daha sonra bu modülü kullarak hareketli ortalamayı hesaplayan modülü tasarlayalım:
--Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity MovingAverage is generic(DataLength : integer := 12; --Veri uzunluğu SamplePower : integer := 5); --Ortalamaya girecek örnek sayısının kuvveti --Örnek sayısı = 2^SamplePower port(Clk, Reset : in std_logic; --Clock ve Reset girişi DataIn : in std_logic_vector(DataLength - 1 downto 0); --Ortalamaya girecek yeni veri Average : out std_logic_vector(DataLength - 1 downto 0)); --Ortalama çıkışı end MovingAverage; architecture Behavioral of MovingAverage is --Kayan ortalama modülünü çağır component MovingAverageModule generic(DataLength : integer := 12; --Veri uzunluğu SumLength : integer := 17); --Toplam verisinin uzunluğu port(Clk, Reset : in std_logic; --Clock ve reset girişi D : in std_logic_vector(DataLength - 1 downto 0); --Veri girişi Q : out std_logic_vector(DataLength - 1 downto 0); --Veri çıkışı SumIn : in std_logic_vector(SumLength - 1 downto 0); --Toplam verisi girişi SumOut : out std_logic_vector(SumLength - 1 downto 0)); --Toplam verisi çıkışı end component; --Verilerin taşınacağı sinyal dizisi type Data_Array is array (2**SamplePower downto 0) of std_logic_vector(DataLength - 1 downto 0); --Toplam verilerinin taşınacağı sinyal dizisi type Sum_Array is array (2**SamplePower downto 0) of std_logic_vector(DataLength + SamplePower - 1 downto 0); --Veri ve toplam verilerinin taşınacağı sinyaller signal DBus : Data_Array; signal SBus : Sum_Array; begin --Modullerin üretilmesi Modules : for i in 0 to 2**SamplePower - 1 generate Module : MovingAverageModule generic map(DataLength, DataLength + SamplePower) port map(Clk, Reset, DBus(i), DBus(i + 1), SBus(i), SBus(i + 1)); end generate; --DBus dizisinin ilk elemanına yeri veriler gönderilir DBus(0) <= DataIn; --SBus dizisinin ilk elemanına 0 gönderilir SBus(0) <= (others => '0'); --Bölme işlemi bitsel kaydırma ile hesaplanır --SBus dizisinin son elemanı SamplePower kadar sağa kaydırılır Average <= SBus(2**SamplePower)(DataLength + SamplePower - 1 downto SamplePower); end Behavioral;
Daha önce ADC128S022 entegresi ile ADC verilerini almıştık. Yazıya buradan ulaşabilirsiniz. Aldığımız verilerin hareketli ortalamasını bularak daha stabil değerler elde edebiliriz.
ADC + Hareketli Ortalama Uygulaması:
--Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity MovingAverageADC is port(Clk, Reset : in std_logic; --Clock ve reset girişi CS, SCLK, DIN : out std_logic; --ADC entegresinin SPI bağlantıları DOUT : in std_logic; --ADC entegresinin SPI bağlantıları LedOut : out std_logic_vector(11 downto 0)); --Led çıkışı end MovingAverageADC; architecture Behavioral of MovingAverageADC is component MovingAverage generic(DataLength : integer := 12; --Veri uzunluğu SamplePower : integer := 5); --Ortalamaya girecek örnek sayısının kuvveti --Örnek sayısı = 2^SamplePower port(Clk, Reset : in std_logic; --Clock ve Reset girişi DataIn : in std_logic_vector(DataLength - 1 downto 0); --Ortalamya girecek yeni veri Average : out std_logic_vector(DataLength - 1 downto 0)); --Ortalama çıkışı end component; component ADC port(Clk : in std_logic; --Clock Girişi CS, SCLK, DIN : out std_logic; --ADC Entegresinin CS, SCLK ve DIN Girişleri DOUT : in std_logic; --ADC Entegresinin DOUT Çıkışı ADCOut : out std_logic_vector(11 downto 0)); --ADC'den okunan 12 bitlik sinyal end component; signal ADCOut : std_logic_vector(11 downto 0); --Hareketli ortalama modülünün clock sinyali signal ClkDiv : std_logic := '0'; begin --Hareketli ortalama modülü için clock bölücü process. --ADC modülün hızı yaklaşık 195ksps olduğundan --clock bölücü ile 50Mhz'den 195khz elde edilir. process(Clk) variable ClkCnt : unsigned(7 downto 0) := (others => '0'); begin if rising_edge(Clk) then if ClkCnt < 127 then ClkCnt := ClkCnt + 1; else ClkDiv <= not ClkDiv; ClkCnt := (others => '0'); end if; end if; end process; --ADC modülünün üretilmesi ADCModule : ADC port map(Clk, CS, SCLK, DIN, DOUT, ADCOut); --Hareketli ortalama modülünün üretilmesi --SamplePower = 5 -> 32 örneğin ortalaması alınıyor. MovingAverageModule : MovingAverage generic map(12, 5) port map(ClkDiv, not Reset, ADCOut, LedOut); end Behavioral;
Video:
aklıma bir şey takıldı aktifseniz sorabilir miyim .