Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

PID controller problem

Hi ,

i am trying to build a pid controller , but for some reason using the vwf file to apply 00011111 for the led and the clk for period of 100 ns, the result of the PID_VAL and integral equation does not show as [x] .. any hep please

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.std_logic_signed.all;

use ieee.numeric_std.all;

entity PID is

port(

left_wheel:out integer;

left_w : out std_logic_vector(0 to 1);

right_wheel:out integer;

right_w : out std_logic_vector(0 to 1);

counter:out integer;

led:in std_logic_vector(0 to 7);

clk:in std_logic

);

end PID;

architecture Behavioral of PID is

TYPE int_array IS ARRAY (0 to 7) OF integer;

constant kp: integer :=80;

constant kd: integer :=80;

constant ki: integer :=50;

constant desired: integer := 4;

constant t_wait : time := 1000 ns;

signal reset : std_logic := '0';

begin

process (clk) is

variable sum : integer:= 0;

variable line_cur, line_prev : integer :=1;

variable time_prev, time_cur : integer := 0;

variable counter_a : integer := 0;

variable pid_val : integer := 0;

variable integral : integer := 0;

variable led_val :int_array := (others => 0);

begin

counter_a := counter_a +1;

counter <= counter_a;

if( clk'event and clk='1') then

pid_val := 0;

integral := 0;

sum := 0;

line_prev := line_cur;

line_cur :=0;

time_prev := time_cur;

for i in 0 to 7 loop

if (led(i)='1')then

led_val(i) := 1;

else

led_val(i) := 0;

end if;

time_cur := counter_a;

sum := sum + led_val(i);

line_cur := line_cur + ((i+1)*led_val(i));

end loop;

line_cur := line_cur/sum;

-- PID controller and drive

integral := integral + ((desired - line_cur)/time_cur);

pid_val := (kp*(desired - line_cur))+ (kd*((line_cur-line_prev)/(time_cur-time_prev)))+ (ki*integral);

-- drive

if ((100- pid_val) < 0) then

left_wheel <= ((-1)*(100-pid_val));

left_w <="10";

else

left_wheel <= (100-pid_val);

left_w <="01";

end if;

if ((100+pid_val) < 0 ) then

right_wheel <= ((-1)*(100+pid_val));

right_w <="10";

else

right_wheel <= (100+pid_val);

left_w <="01";

end if;

end if;

end process;

reset <='1'after 40 ns, '0' after 80 ns;

end Behavioral;

1 Reply

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    First there are a few VHDL problems

    use IEEE.std_logic_signed.all;
    use ieee.numeric_std.all;

    Don't use those two libraries together, it can give very strange results. You'd better only use numeric_std, which is standard, and use its signed and unsigned types instead of std_logic_vector whenever you have a signal with a range of bits representing an integer value.

    counter_a := counter_a +1;
    counter <= counter_a;
    Those two lines should be inside the if( clk'event and clk='1'). I'm not sure Quartus will know how to synthesize your code when it is written like this, and what it would attempt to synthesize would most probably not be what you want. A VHDL simulator will increase twice counter_a for each clock cycle, which will also be different from a synthesized version.

    if( clk'event and clk='1') then
    pid_val := 0;
    integral := 0;
    You reinitialize integral to 0 on each clock cycle, so you no longer have an integral.

    integral := integral + ((desired - line_cur)/time_cur);
    I think this line is wrong. First you need to use the difference between the previous time value and the current one, instead of just the absolute time, and for an integral value you need to multiply by the time, not divide by it.

    Each time you write time_cur-time_prev you can just replace it by 1.

    reset <='1'after 40 ns, '0' after 80 ns;
    You don't use the reset signal anywhere in your code.

    Now for the simulation itself. Are you simulating from Quartus? If yes you should consider switching to Modelsim instead. It is a bit more difficult to get started, but it is much more powerful. The Quartus simulator isn't very good, and not supported any more.

    When you run the simulation, do you see the clock cycling? What kind of outputs do you see?