library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity PI is generic( Clock_freq : integer :=50_000_000; kP : integer := 1; kI : integer := 50_000_000; TOP_VALUE : signed (7 downto 0) :="01111111"; -- +127 MID1_VALUE : signed (7 downto 0) :="01010000"; -- +80 MID2_VALUE : signed (7 downto 0) :="10110000"; -- -80 BOT_VALUE : signed (7 downto 0) :="10000000" -- -128 ); port( riferimento : in signed (7 downto 0); -- velocità desiderata feedback : in signed (7 downto 0); -- uscita del rilevatore dell' encoder clock : in std_logic; uscita : out signed (7 downto 0) ); end entity; architecture arch of PI is signal stato : std_logic_vector (1 downto 0); signal errore : signed (7 downto 0) :="00000000"; signal errore_cumulativo : signed (7 downto 0) :="00000000";-- l'errore cumulativo è da considerare come la sommatoria da 0 ad infinito per il contributo integrale signal P : signed (7 downto 0) :="00000000";-- signal I : signed (7 downto 0) :="00000000";-- signal PI : signed (7 downto 0) :="00000000";-- begin process (riferimento, feedback, clock) is begin if clock'event and clock='1'then errore<= riferimento - feedback; -- calcolo l'errore come la differenza tra il riferimento ed il feedback dell' encoder errore_cumulativo<=errore_cumulativo + errore; -- considero errore cumulativo come la somma dell'errore in ogni periodo P<=resize(errore * kP,P'length); -- calcolo P come prodotto dell'errore per il guadagno Kp I<=resize(errore_cumulativo*kI*(1/Clock_freq),I'length);-- calcolo I come la sommatoria dell'errore * Ki * il periodo del clock in modo da calcolare anche se in maniera approssimata, l'area sottesa alla curva ---------- controllo dei limiti --------------------- -- in questa sezione faccio un controllo di PI: se questo valore si trova prima di -80 o dopo 80, ad ogni colpo di clock fa la verifica -- del valore che dovrebbe assumere al prossimo colpo, in modo da evitare l'overflow e clampare il valore al valore massimo o 0 e nel contempo annullare l'errore end if; if clock'event and clock='0' then PI<=resize(P+I,uscita'length); if PI<= MID1_VALUE and PI>=MID2_VALUE then stato<="00"; -- -80 MID1_VALUE then stato<="10"; -- PI> 80 end if; case stato is when "00" => uscita<=PI; when "01" => if PI+errore>0 then PI<=BOT_VALUE; -- errore_cumulativo<=errore_cumulativo-errore; errore<="00000000"; -- ti devi stare fermo o fai danni uscita<=BOT_VALUE; else uscita<=PI; end if; when "10" => if PI+errore<0 then PI<=TOP_VALUE; -- errore_cumulativo<=errore_cumulativo-errore; errore<="00000000"; -- fermati o fai danni uscita<=TOP_VALUE; else uscita<=PI; end if; when others => uscita<="00000000"; -- stato di sicurezza del motore end case ; end if; end process; end architecture;