www.mikrocontroller.net

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


Autor: Moe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity umdrehzaehler is
  Port ( 
--Reset : in std_logic;
  clock : in std_logic;
  SA: in std_logic;
  SB: in std_logic;
  SC: in std_logic;
  Data : out std_logic_vector(7 downto 0));
end umdrehzaehler;

architecture Behavioral of umdrehzaehler is
  SIGNAL posc,negc : integer;
  SIGNAL shift_reg : std_logic_vector(7 downto 0); 
  
begin

  process (SA) -- Prozess zur Abfrage des Sensors A
  begin
    FOR i IN 0 to 5 LOOP
      shift_reg(i)<=shift_reg(i+2);
    END LOOP;
    shift_reg(6)<='0';
    shift_reg(7)<='1';
  end process;

  process (SB) -- Prozess zur Abfrage des Sensors B
  begin
    FOR i IN 0 to 5 LOOP
      shift_reg(i)<=shift_reg(i+2);  
    END LOOP;
    shift_reg(6)<='1';
    shift_reg(7)<='0';
  end process;

  process (SC) -- Prozess zur Abfrage des Sensors C
  begin
    FOR i IN 0 to 5 LOOP
      shift_reg(i)<=shift_reg(i+2);  
    END LOOP;
    shift_reg(6)<='1';
    shift_reg(7)<='1';
  end process;

  process (clock) -- Prozess zur Abfrage, ob eine Umdrehung vollständig ist und in welche Richtung
  begin
      FOR i IN 0 to 7 LOOP
      Data(i)<=shift_reg(i);  
    END LOOP;
      case shift_reg is
      when "01101101" => -- Volle Umdrehung im Uhrzeigersinn entdeckt
        posc<= posc+1;
        shift_reg(0)<='0';
        shift_reg(1)<='0';
        shift_reg(2)<='0';
        shift_reg(3)<='0';
        shift_reg(4)<='0';
        shift_reg(5)<='0';
      when "10110110" => -- Volle Umdrehung im Uhrzeigersinn entdeckt
        posc<= posc+1;
        shift_reg(0)<='0';
        shift_reg(1)<='0';
        shift_reg(2)<='0';
        shift_reg(3)<='0';
        shift_reg(4)<='0';
        shift_reg(5)<='0';
      when "11011011" => -- Volle Umdrehung im Uhrzeigersinn entdeckt
        posc<= posc+1;
        shift_reg(0)<='0';
        shift_reg(1)<='0';
        shift_reg(2)<='0';
        shift_reg(3)<='0';
        shift_reg(4)<='0';
        shift_reg(5)<='0';
      when "01111001"=> -- Volle Umdrehung gegen den Uhrzeigersinn
        negc <= negc+1;
        shift_reg(0)<='0';
        shift_reg(1)<='0';
        shift_reg(2)<='0';
        shift_reg(3)<='0';
        shift_reg(4)<='0';
        shift_reg(5)<='0';
      when "11100111" => -- Volle Umdrehung gegen den Uhrzeigersinn
        negc <= negc+1;
        shift_reg(0)<='0';
        shift_reg(1)<='0';
        shift_reg(2)<='0';
        shift_reg(3)<='0';
        shift_reg(4)<='0';
        shift_reg(5)<='0';
      when "10011110" => -- Volle Umdrehung gegen den Uhrzeigersinn
        negc <= negc+1;
        shift_reg(0)<='0';
        shift_reg(1)<='0';
        shift_reg(2)<='0';
        shift_reg(3)<='0';
        shift_reg(4)<='0';
        shift_reg(5)<='0';
      when others =>
negc <= negc+1;
negc <= negc-1;
      end case;
    
    
  end process;

   

end Behavioral;

Ideen?

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zeter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Moe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
process(clk)
begin
  if rising_edge(clk) then
    a_in  <= A;
    a_old <= a_in;
    b_in  <= B;
    b_old <= b_in;
  end if;
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?

Autor: Stefan Wimmer (wswbln)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moe wrote:
 process(clk)
 begin
   if rising_edge(clk) then
     a_in  <= A;
     a_old <= a_in;
     b_in  <= B;
     b_old <= b_in;
   end if;
 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.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Alexander L. (moe)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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

Gruß

Ralf
-- QUAD.vhd
-- --------------------------------------------
--  Quadrature Decoder State Machine
-- --------------------------------------------
-- (c) 2004 - B. Cuzeau, ALSE
-- http://www.alse-fr.com
-- Contact : info@alse-fr.com
-- Notes :
-- * A and B must absolutely be resynchronized outside !
-- * FSM State encoding should be sequential/binary or custom (like here)
-- * Implemented as re-synchronized, one-process, Mealy State machine.
-- * Change the counter size directly in the port declaration.
-- * Cnt (n downto 2) returns the position in full turns.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;


entity QUAD is
  port(
    A, B : in  std_logic;                     -- must absolutely be resynchronized outside
    Rst  : in  std_logic;
    Clk  : in  std_logic;
    Cnt  : out std_logic_vector(7 downto 0);  -- unsigned value !
    Dir  : out std_logic
  );
end entity QUAD;


architecture behavioral of QUAD is

  subtype SLV2 is std_logic_vector (1 downto 0);
  attribute enum_encoding : string;

  type state_t is (Boot, S00, S01, S10, S11);
  attribute enum_encoding of state_t : type is "100 000 001 010 011";
  signal state                       : state_t;

  signal Count : unsigned(Cnt'range);

begin
  Cnt <= std_logic_vector(Count);

  process (Rst, Clk)
  begin
    if (Rst = '1') then
      State <= Boot;
      Count <= (others => '0');
      Dir   <= '0';
    elsif rising_edge(Clk) then
      case State is
        when Boot =>
          case SLV2'(A & B) is
            when "00" =>
              State <= S00;
              
            when "10" =>
              State <= S10;
              
            when "11" =>
              State <= S11;
              
            when "01" =>
              State <= S01;
              
            when others =>
              null;
          end case;

        when S00 =>
          case SLV2'(A & B) is
            when "10" =>
              State <= S10;
              Count <= Count + 1;
              Dir   <= '1';
              
            when "11" =>
              null;
            -- possible : State <= S11;
              
            when "01" =>
              State <= S01;
              Count <= Count - 1;
              Dir   <= '0';
              
            when others =>
              null;
          end case;

        when S10 =>
          case SLV2'(A & B) is
            when "00" =>
              State <= S00;
              Count <= Count - 1;
              Dir   <= '0';
              
            when "11" =>
              State <= S11;
              Count <= Count + 1;
              Dir   <= '1';
              
            when "01" =>
              null;
            -- possible : State <= S01;
              
            when others =>
              null;
          end case;

        when S11 =>
          case SLV2'(A & B) is
            when "10" =>
              State <= S10;
              Count <= Count - 1;
              Dir   <= '0';
              
            when "01" =>
              State <= S01;
              Count <= Count + 1;
              Dir   <= '1';
              
            when "00" =>
              null;
            -- possible : State <= S00;
              
            when others =>
              null;
          end case;

        when S01 =>
          case SLV2'(A & B) is
            when "11" =>
              State <= S11;
              Count <= Count - 1;
              Dir   <= '0';
              
            when "00" =>
              State <= S00;
              Count <= Count + 1;
              Dir   <= '1';
              
            when "10" =>
              null;
           -- possible : State <= S10;
              
            when others =>
              null;
          end case;

        when others =>
          State <= Boot;
      end case;
    end if;
  end process;
end behavioral;

Autor: Alexander L. (moe)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.
process (clk)
begin
  if rising_edge(clk) then
    if ce='1' then
      if dir='1' then
        cnt <= cnt+1;
      else
        cnt <= cnt-1;
      end if; 
    end if;
  end if;
end process;

MFg
Falk

Autor: Alexander L. (moe)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.