Forum: FPGA, VHDL & Co. 3 Sensoren in ein Register


von Moe (Gast)


Lesenswert?

Hallo,

ich versuche folgendes in VHDL zu realisieren

Es gibt 3 Sensoren (A,B,C) die binär sind(0,1), die neben der clock 
meine Inputs sind.

Jetzt will ich diese Sensoren bzw. einen Wert ('01' für A, '10' für B 
und '11' für C) in ein Shift Register eintragen.

Anhand der parallelen Augabe des Registers erkenne ich dann im 
"Hauptprozess", ob ich einen gewissen Zyklus gefunden habe und wenn ja, 
zähle einen Counter bzw 2 Counter hoch.

Mein Problem ist das egal wie ich das versuche, stehe ich ich immer mit 
"can't resolve multiple constant drivers" da.
Ich verstehe ja auch warum. Es könnten ja 2 Sensoren gleichzeitig 
auslösen. Aber was tun?

Das ganze soll die Umdrehungen eines Gewindes o.ä. messen. Also wenn die 
Senoren z.B. in der Reihenfolge A,B,C,A auslösen habe ich eine 
Umdrehung.


Ich hatte mir das ganze so gedacht:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity umdrehzaehler is
7
  Port ( 
8
--Reset : in std_logic;
9
  clock : in std_logic;
10
  SA: in std_logic;
11
  SB: in std_logic;
12
  SC: in std_logic;
13
  Data : out std_logic_vector(7 downto 0));
14
end umdrehzaehler;
15
16
architecture Behavioral of umdrehzaehler is
17
  SIGNAL posc,negc : integer;
18
  SIGNAL shift_reg : std_logic_vector(7 downto 0); 
19
  
20
begin
21
22
  process (SA) -- Prozess zur Abfrage des Sensors A
23
  begin
24
    FOR i IN 0 to 5 LOOP
25
      shift_reg(i)<=shift_reg(i+2);
26
    END LOOP;
27
    shift_reg(6)<='0';
28
    shift_reg(7)<='1';
29
  end process;
30
31
  process (SB) -- Prozess zur Abfrage des Sensors B
32
  begin
33
    FOR i IN 0 to 5 LOOP
34
      shift_reg(i)<=shift_reg(i+2);  
35
    END LOOP;
36
    shift_reg(6)<='1';
37
    shift_reg(7)<='0';
38
  end process;
39
40
  process (SC) -- Prozess zur Abfrage des Sensors C
41
  begin
42
    FOR i IN 0 to 5 LOOP
43
      shift_reg(i)<=shift_reg(i+2);  
44
    END LOOP;
45
    shift_reg(6)<='1';
46
    shift_reg(7)<='1';
47
  end process;
48
49
  process (clock) -- Prozess zur Abfrage, ob eine Umdrehung vollständig ist und in welche Richtung
50
  begin
51
      FOR i IN 0 to 7 LOOP
52
      Data(i)<=shift_reg(i);  
53
    END LOOP;
54
      case shift_reg is
55
      when "01101101" => -- Volle Umdrehung im Uhrzeigersinn entdeckt
56
        posc<= posc+1;
57
        shift_reg(0)<='0';
58
        shift_reg(1)<='0';
59
        shift_reg(2)<='0';
60
        shift_reg(3)<='0';
61
        shift_reg(4)<='0';
62
        shift_reg(5)<='0';
63
      when "10110110" => -- Volle Umdrehung im Uhrzeigersinn entdeckt
64
        posc<= posc+1;
65
        shift_reg(0)<='0';
66
        shift_reg(1)<='0';
67
        shift_reg(2)<='0';
68
        shift_reg(3)<='0';
69
        shift_reg(4)<='0';
70
        shift_reg(5)<='0';
71
      when "11011011" => -- Volle Umdrehung im Uhrzeigersinn entdeckt
72
        posc<= posc+1;
73
        shift_reg(0)<='0';
74
        shift_reg(1)<='0';
75
        shift_reg(2)<='0';
76
        shift_reg(3)<='0';
77
        shift_reg(4)<='0';
78
        shift_reg(5)<='0';
79
      when "01111001"=> -- Volle Umdrehung gegen den Uhrzeigersinn
80
        negc <= negc+1;
81
        shift_reg(0)<='0';
82
        shift_reg(1)<='0';
83
        shift_reg(2)<='0';
84
        shift_reg(3)<='0';
85
        shift_reg(4)<='0';
86
        shift_reg(5)<='0';
87
      when "11100111" => -- Volle Umdrehung gegen den Uhrzeigersinn
88
        negc <= negc+1;
89
        shift_reg(0)<='0';
90
        shift_reg(1)<='0';
91
        shift_reg(2)<='0';
92
        shift_reg(3)<='0';
93
        shift_reg(4)<='0';
94
        shift_reg(5)<='0';
95
      when "10011110" => -- Volle Umdrehung gegen den Uhrzeigersinn
96
        negc <= negc+1;
97
        shift_reg(0)<='0';
98
        shift_reg(1)<='0';
99
        shift_reg(2)<='0';
100
        shift_reg(3)<='0';
101
        shift_reg(4)<='0';
102
        shift_reg(5)<='0';
103
      when others =>
104
negc <= negc+1;
105
negc <= negc-1;
106
      end case;
107
    
108
    
109
  end process;
110
111
   
112
113
end Behavioral;

Ideen?

Nebenfrage:
Warum sollte man keine Variablen benutzen? Wo liegt der Nachteil?

von Falk B. (falk)


Lesenswert?

@ Moe (Gast)

>Jetzt will ich diese Sensoren bzw. einen Wert ('01' für A, '10' für B
>und '11' für C) in ein Shift Register eintragen.

Das ist ein Multiplexer Multiplexen.

>Mein Problem ist das egal wie ich das versuche, stehe ich ich immer mit
>"can't resolve multiple constant drivers" da.
>Ich verstehe ja auch warum. Es könnten ja 2 Sensoren gleichzeitig
>auslösen. Aber was tun?

Beschreibe mal deine Sensoren genauer. Du sprichtst in Rätseln.

>Das ganze soll die Umdrehungen eines Gewindes o.ä. messen. Also wenn die
>Senoren z.B. in der Reihenfolge A,B,C,A auslösen habe ich eine
>Umdrehung.

Drehgeber?

>Ideen?

Dein VHDL ist ziemlicher Nonsense. Tut mir leid. Da musst du nochmal an 
die Grundlagen ran.

>Nebenfrage:
>Warum sollte man keine Variablen benutzen? Wo liegt der Nachteil?

Weil der Unterschied von Anfängern nur schwer verstanden wird. Und 
zwingend braucht man die am Anfang nicht.

MFG
Falk

von Zeter (Gast)


Lesenswert?

@Falk Er lernt mehr, wenn Du ihm genu erklärst, was passiert.

@Moe: Du treibst 3 Leitungen, nämlich die Registereingänge aus 3 
Quellen. Taste die 3 Sensoren mit entsprechender Frequenz ab und schiebe 
die Codes NACHEINANDER in die Register.

von Moe (Gast)


Lesenswert?

@ Falk:
Ja das ganze ist wohl ein Drehgeber mit 3 Sensoren. Ziel ist es später 
auch halbe Drehungen und nicht gewollte Hin-und-her Bewegungen zu 
detektieren, aber soweit bin ich ja noch nicht.

Das Drehgeber VHDL-Beispiel in dem Link von dir verstehe ich nicht so 
recht.
1
process(clk)
2
begin
3
  if rising_edge(clk) then
4
    a_in  <= A;
5
    a_old <= a_in;
6
    b_in  <= B;
7
    b_old <= b_in;
8
  end if;
9
end process;

Ist in "a_in" und "a_old" bzw. "b_in" und "b_old" nicht immer der 
gleiche Wert, da ja erst das Input-Signal "A" in "a_in" geschrieben wird 
und dann "a_in" an "a_old" weitergereicht wird?
Oder führt er bei Ausführung von

a_in <= A;

den unteren Prozess des Codes aus(da ja "a_in" verändert wurde) und 
kehrt erst nach dessen Beendigung zur nächsten Zeile des oberen Prozess 
des Codes zurück?

Sorry, wenn ich wieder in Rätseln schreibe und danke für die Geduld.


@Zeter:
Wie mache ich das am Besten? Ist denn mein Anstatz mit einem Prozess pro 
Sensor richtig? Oder eher so wie in dem Drehgeber Beispiel von oben?

von Stefan W. (wswbln)


Lesenswert?

Moe wrote:
1
 process(clk)
2
 begin
3
   if rising_edge(clk) then
4
     a_in  <= A;
5
     a_old <= a_in;
6
     b_in  <= B;
7
     b_old <= b_in;
8
   end if;
9
 end process;

> Ist in "a_in" und "a_old" bzw. "b_in" und "b_old" nicht immer der
> gleiche Wert, da ja erst das Input-Signal "A" in "a_in" geschrieben wird
> und dann "a_in" an "a_old" weitergereicht wird?
> Oder führt er bei Ausführung von
>
> a_in <= A;
>
> den unteren Prozess des Codes aus(da ja "a_in" verändert wurde) und
> kehrt erst nach dessen Beendigung zur nächsten Zeile des oberen Prozess
> des Codes zurück?

NEIN!
In VHDL gibt es innerhalb eines geclockten Prozesses kein vor und 
zurück. Du denkst zu sehr im Rahmen von Programmen und Controllern. VHDL 
ist KEINE Programmiersprache, sondern eine 
Hardeware-Beschreibungssprache. Es "passiert" innerhalb des obigen 
Prozesses alles gleichzeitig! Es handelt sich um Gatter und FlipFlops, 
nicht um eine Maschine, die nacheinander abtastet und reagiert.

von Falk B. (falk)


Lesenswert?

@ Moe (Gast)

>Ja das ganze ist wohl ein Drehgeber mit 3 Sensoren. Ziel ist es später

Mit drei? Dann hat der neben den beiden Spuren A und B noch einen Index.

>auch halbe Drehungen und nicht gewollte Hin-und-her Bewegungen zu
>detektieren, aber soweit bin ich ja noch nicht.

Sinnvollerweise solltest du aber hier die komplette Lösung direkt 
anstreben, zumal sie hier recht einfach ist. Denn der Dekoder liefert 
die Ansteuerisgnale für eien Up-Down counter. Einfacher geht es kaum.

>Wie mache ich das am Besten? Ist denn mein Anstatz mit einem Prozess pro
>Sensor richtig? Oder eher so wie in dem Drehgeber Beispiel von oben?

Eher wie der Drehgeber im Tutorial. Denn du bist gerade dabei, das Rad 
neu zu erfinden. Als Fünfeck!

MFG
Falk

von Alexander L. (moe)


Lesenswert?

Ok dann werde ich mich mal an die Modifikation des gegebenen Drehgebers 
begeben.

Ich hab den Code mal in Quartus II Web Edition geladen und simuliert, 
allerdings komme ich mit den Ausgaben nicht so ganz zurecht.

In der Beschreibung stand:

"Der folgende Code tastet die beiden Quadratursignale ab und generiert 
daraus ein UP/DOWN Signal sowie ein CE für einen Zähler, mit dem dann 
die aktuelle Position erfasst werden kann"

Soweit ich das verstehe sagt UP/DOWN an in welche Richtung sich das 
ganze gerade dreht.

CE ist doch immer eins, wenn eine Umdrehung festgestellt wurde, oder?

Die Ergebnisse der Simulation unterstützen meine Vermutung aber nicht. 
Wenn ich als einfaches Beispiel 3 mal nacheinander Sensor A auslöse aber 
kein mal Sensor B  , löst trotzdem CE 2 mal aus.

Das verwirrt mich alles ein wenig...

von Falk B. (falk)


Lesenswert?

@ Alexander L. (moe)

>Soweit ich das verstehe sagt UP/DOWN an in welche Richtung sich das
>ganze gerade dreht.

Ja, Nomen est omen.

>CE ist doch immer eins, wenn eine Umdrehung festgestellt wurde, oder?

NEIN, wenn ein Schritt festgestellt wurde. Eine Umdrehung besteht 
aus vielen Schritten, abhängig vom Drehgeber.

>Die Ergebnisse der Simulation unterstützen meine Vermutung aber nicht.
>Wenn ich als einfaches Beispiel 3 mal nacheinander Sensor A auslöse aber
>kein mal Sensor B  , löst trotzdem CE 2 mal aus.

Was heist denn "auslösen"? Sprich doch mal klar in der Sprache der 
Digitaltechnik. Ausserdem solltest du noch einmal den Artikel 
Drehgeber genau und in Ruhe studieren.

>Das verwirrt mich alles ein wenig...

Beruht auf Gegenseiigkeit.

MFg
Falk

von Ralf (Gast)


Lesenswert?

Hallo,

vielleicht ist dieser Code ganz nützlich.
Ist nicht von mir und ich habe ihn nicht getested.

Gruß

Ralf
1
-- QUAD.vhd
2
-- --------------------------------------------
3
--  Quadrature Decoder State Machine
4
-- --------------------------------------------
5
-- (c) 2004 - B. Cuzeau, ALSE
6
-- http://www.alse-fr.com
7
-- Contact : info@alse-fr.com
8
-- Notes :
9
-- * A and B must absolutely be resynchronized outside !
10
-- * FSM State encoding should be sequential/binary or custom (like here)
11
-- * Implemented as re-synchronized, one-process, Mealy State machine.
12
-- * Change the counter size directly in the port declaration.
13
-- * Cnt (n downto 2) returns the position in full turns.
14
library IEEE;
15
use IEEE.std_logic_1164.all;
16
use IEEE.numeric_std.all;
17
18
19
entity QUAD is
20
  port(
21
    A, B : in  std_logic;                     -- must absolutely be resynchronized outside
22
    Rst  : in  std_logic;
23
    Clk  : in  std_logic;
24
    Cnt  : out std_logic_vector(7 downto 0);  -- unsigned value !
25
    Dir  : out std_logic
26
  );
27
end entity QUAD;
28
29
30
architecture behavioral of QUAD is
31
32
  subtype SLV2 is std_logic_vector (1 downto 0);
33
  attribute enum_encoding : string;
34
35
  type state_t is (Boot, S00, S01, S10, S11);
36
  attribute enum_encoding of state_t : type is "100 000 001 010 011";
37
  signal state                       : state_t;
38
39
  signal Count : unsigned(Cnt'range);
40
41
begin
42
  Cnt <= std_logic_vector(Count);
43
44
  process (Rst, Clk)
45
  begin
46
    if (Rst = '1') then
47
      State <= Boot;
48
      Count <= (others => '0');
49
      Dir   <= '0';
50
    elsif rising_edge(Clk) then
51
      case State is
52
        when Boot =>
53
          case SLV2'(A & B) is
54
            when "00" =>
55
              State <= S00;
56
              
57
            when "10" =>
58
              State <= S10;
59
              
60
            when "11" =>
61
              State <= S11;
62
              
63
            when "01" =>
64
              State <= S01;
65
              
66
            when others =>
67
              null;
68
          end case;
69
70
        when S00 =>
71
          case SLV2'(A & B) is
72
            when "10" =>
73
              State <= S10;
74
              Count <= Count + 1;
75
              Dir   <= '1';
76
              
77
            when "11" =>
78
              null;
79
            -- possible : State <= S11;
80
              
81
            when "01" =>
82
              State <= S01;
83
              Count <= Count - 1;
84
              Dir   <= '0';
85
              
86
            when others =>
87
              null;
88
          end case;
89
90
        when S10 =>
91
          case SLV2'(A & B) is
92
            when "00" =>
93
              State <= S00;
94
              Count <= Count - 1;
95
              Dir   <= '0';
96
              
97
            when "11" =>
98
              State <= S11;
99
              Count <= Count + 1;
100
              Dir   <= '1';
101
              
102
            when "01" =>
103
              null;
104
            -- possible : State <= S01;
105
              
106
            when others =>
107
              null;
108
          end case;
109
110
        when S11 =>
111
          case SLV2'(A & B) is
112
            when "10" =>
113
              State <= S10;
114
              Count <= Count - 1;
115
              Dir   <= '0';
116
              
117
            when "01" =>
118
              State <= S01;
119
              Count <= Count + 1;
120
              Dir   <= '1';
121
              
122
            when "00" =>
123
              null;
124
            -- possible : State <= S00;
125
              
126
            when others =>
127
              null;
128
          end case;
129
130
        when S01 =>
131
          case SLV2'(A & B) is
132
            when "11" =>
133
              State <= S11;
134
              Count <= Count - 1;
135
              Dir   <= '0';
136
              
137
            when "00" =>
138
              State <= S00;
139
              Count <= Count + 1;
140
              Dir   <= '1';
141
              
142
            when "10" =>
143
              null;
144
           -- possible : State <= S10;
145
              
146
            when others =>
147
              null;
148
          end case;
149
150
        when others =>
151
          State <= Boot;
152
      end case;
153
    end if;
154
  end process;
155
end behavioral;

von Alexander L. (moe)


Lesenswert?

Ja du hast wohl recht.Ich werde mir das Ganze erstmal in Ruhe zu Gemüte 
führen.

Mit scheint ich verstehe nicht wie ein Drehgeber wirklich funktioniert. 
Ich hatte da eine etwas zu simple Vorstellung.

von Falk B. (falk)


Lesenswert?

@ Ralf (Gast)

>vielleicht ist dieser Code ganz nützlich.

Glaub ich kaum.

>Ist nicht von mir und ich habe ihn nicht getested.

Warum stellst du dann solchen aufgeblasenen, akademischen Unsinn hier 
rein?

Man muss nur ein KLEIN wenig VHDL an den Code aus dem Wikiartikel 
anfügen, und schon werden die Pulse korrekt gezählt.
1
process (clk)
2
begin
3
  if rising_edge(clk) then
4
    if ce='1' then
5
      if dir='1' then
6
        cnt <= cnt+1;
7
      else
8
        cnt <= cnt-1;
9
      end if; 
10
    end if;
11
  end if;
12
end process;

MFg
Falk

von Alexander L. (moe)


Lesenswert?

@Falk
Ich hab mir das mal genauer angeguckt.
Wie der Code in dem Beispiel aus deinem Link funktioniert, verstehe ich 
jetzt im Ansatz, aber ich habe festgestellt, das es etwas Overkill ist 
für das was ich will.

Mein Ziel ist es bei einer solchen Konstruktion

http://img88.imageshack.us/img88/2941/3sensoroa9.th.jpg

eine Umdrehung(im Uhrzeigersinn) zu messen, wenn der kleine Knubbel in 
der Zeichnung bei z.B. A,B,C,A vorbeikommt. Das meinte ich auch mit 
"auslösen" der Sensoren.

Wenn ich das mit dem Drehgeber richtig verstehe, besitzt dieser nicht 
einen Knubbel, sondern eher Knubbel > 30 und 2 phasenverschobene 
Sensoren zur Bestimmung der Drehrichtung und des Winkels, sowie meist 
einen Nullindex zur Feststellung der Anfangsposition.

Entschuldige, wenn ich mich auf Grund meines Nichtwissens 
missverständlich ausgedrückt habe.

Auf welchen Wikiartikel beziehst du dich in deiner Antwort auf Ralfs 
Beitrag?

von Falk B. (falk)


Lesenswert?

@ Alexander L. (moe)

>Wenn ich das mit dem Drehgeber richtig verstehe, besitzt dieser nicht
>einen Knubbel, sondern eher Knubbel > 30 und 2 phasenverschobene
>Sensoren zur Bestimmung der Drehrichtung und des Winkels, sowie meist
>einen Nullindex zur Feststellung der Anfangsposition.

Ja. Und damit kann man dein Problem wunderbar lösen. Sogar mit Digital 
einstellbaren Knubbeln.

>Auf welchen Wikiartikel beziehst du dich in deiner Antwort auf Ralfs
>Beitrag?

Drehgeber

MFG
Falk

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.