Ultraschallentfernungsmessung mittels FPGA

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

von Thomas Eichstetter, Nicole Elsner ; Mentor: Dr.Ing. MBA Thomas Fuhrmann

Dieser Artikel ist ein Anfängerprojekt.

Einleitung

Zugegeben, das Projekt „Ultraschall-Entfernungsmessung“ findet sich in diversen Variationen an einigen Stellen im Netz. Warum haben wir nun das gleiche Ziel, aber wollen es wieder in einer abgewandelten Form vorstellen? Als Studenten im Bereich Elektro- und Informationstechnik ist es uns besonders wichtig, die teilweise sehr theoretisch aufgebauten Vorlesungen durch praktische Aufgaben zu vertiefen. Neben den grundsätzlichen Dingen wie Erstellen einer Platine und Anwendung deren Bausteine, lag es uns auch am Herzen die bisher sehr rudimentären VHDL-Kenntnisse auszubauen und in einem praktischen Projekt anzuwenden. Damit ist ein neues Projekt geboren, das zwar ähnlich bereits existiert, aber nur in unserer Form angemessen auf unser Studium eingeht.


Abb.1 Gesamtansicht


Eine gewisse Grundausrüstung ist Voraussetzung für das Gelingen des Projektes. So gehört ein Oszilloskop ebenso zum Equipment wie die Materialen zum Herstellen einer Platine und Programme zum Erstellen von Schaltnetzen und Simulationen. Diese Programme stehen im Internet teilweise kostenlos zur verfügung. Als kostspieligerer Bestandteil ist das FPGA (Field Programmable Gate Array) zu nennen, welches auf einem Evaluationsboard angebracht und mit entsprechender Entwicklungsumgebung für das folgende Projekt geeignet ist.

Um das hier beschriebene Projekt nachzustellen, wird folgende Ausrüstung benötigt:

  • SwitcherCAD IV LTSpice
  • EAGLE Layout Editor
  • Xilinx 9.1 ISE
  • Xilinx Spartan – 3
  • diverse Bauteile (darunter Z-Diode, Operationsverstärker, Transistoren)
  • Ultraschallsender und -empfänger
  • Spannungsversorgung
  • analoges oder digitales Oszilloskop


Als besonders nützlich hat sich ein Multimeter und Funktionsgenerator gezeigt. Grundkenntnisse in Schaltungstechnik, Berechnungen in elektrischer Netzwerke, Bauelemente und VHDL sind hilfreich.

Präbeginn

Idee

Abb.2 Reflexionsdarstellung des Schalls

Eine Sendekapsel erzeugt Schall, der an einem beliebigen Objekt reflektiert und von einer Empfängerkapsel aufgenommen wird. Durch Messung der Laufzeit, Dauer von Senden bis zum Empfangen, kann unter Berücksichtigung der Schallgeschwindigkeit die Entfernung des Objektes bestimmt werden. Diese zeitliche Differenz wird durch das FPGA und die selbst erstellte Platine aufgenommen und weiterverarbeitet.








Schnittstellen festlegen

Um verschiedene Teilprojekte erfolgreich miteinander zu verknüpfen, wird zu Anfang die Schnittstelle festgelegt, die sich hier zwischen der selbsterstellten Platine und dem FPGA befindet. An der Schnittstelle liegen zwei zu definierende Signale an, Sendeimpuls und Empfangssignal, die wie folgt aus Sicht des FPGAs festgelegt sind:

Signalart Eigenschaft
Sendeimpulse 1 Ausgangssignal mit CMOS-Pegel Positive Logik 7 Rechteckimpulse auf 3,3V mit f=40kHz ungefähr alle 30ms
Empfangssignal 1 Eingangssingal mit CMOS-Pegel Positive Logik Highimpuls erst bei Erhalten des Echos, spätere Impulse zwischen dem ersten

Highimpuls und der nächsten Sendesequenz haben keinen Einfluss

Essentielle Bausteine

Sender-, Empfängerkapsel

Abb.3 Ultraschallkapsel

Bei dem Ultraschallempfänger bzw. -sender wird der piezoelektrische Effekt genutzt. Der sogenannte Piezokristall wechselwirkt mit Spannung, beginnt dadurch seine Form zu ändern und sende Schallwellen aus. Wird hingegen Schall empfangen, so tritt eine Änderung der elektrischen Polarisation auf und Spannung wird erzeugt. Bei der Ultraschallentfernungsmessung benötigen wir beide Fälle, sowohl die Erzeugung von Schall, als auch Detektion.







FPGA

Abb.4 FPGA
Abb.5 Evaluationsboard

Die CMOS Komponenten im konfigurierbaren Logikbaustein erhalten durch das Programm den Befehl sich auf bestimmte Weise zu verschalten. Damit werden unterschiedliche Gatter (AND, NOR, usw.) realisiert, die zusammen die Hardware des Programmes darstellen. Ein großer Vorteil des FPGA gegenüber Mikrocontrollern ist die Unabhängigkeit der Anzahl der Messungen vom Timer, da im mehrere Messungen parallel laufen können. Dadurch ist es einfacher das Projekt weiter auszubauen.






Operationsverstärker

Dieses Bauteil kann auf simple Weise sämtliche Verstärkungseigenschaften entwickeln. So ist eine Verwendung als Komparator, Filter, Verstärker, Integrator usw. möglich. Im vorgestellten Projekt werden invertierende Verstärker und Komparatoren benötigt.


Aufteilung in Module - Baukastenprinzip

Um die Übersicht besonders bei großen Projekten nicht zu verlieren, ist es ratsam das Netzwerk in einzelne Module zu unterteilen und diese Stück für Stück zu entwickeln. Erst wenn das einzelne Teilprojekt einsatzbereit ist, wird es mit den Übrigen verknüpft. So wird gewährleistet, dass Fehler im Modul nicht in andere Bereiche einfließen und damit schwer festzustellende Störungen verursacht.

Spannungsversorgung

Abb.6 FPGA

Diese Schaltungsteile sind zuständig für die Spannungsversorgung der Bauteile. Mit den Kondensatoren C5 und C6 wird sichergestellt, dass die Betriebsspannung durch kurze Stromimpulse nicht zusammenbricht. Als Ursache dieses Problems ist ein evtl. hoher Innenwiderstand der Spannungsversorgung zu nennen. Die Diode D2 schützt die Schaltung vor falscher Polung.

Mit den zwei Widerständen R7 und R8 wird die Versorgungsspannung VCC halbiert und als neues Bezugspotential VCC/2 verwendet. Die Schwingung der Eingangssignale bewegt sich damit um dieses Potential. Der damit entstandene Offset von VCC/2 kann später durch den Kondensator C3 wieder entfernt werden.

Nachdem die Versorgungsspannung festgelegt ist, wird der Komparator IC2A (vgl. Bild 12) als Ausgangsbauteil für die Funktionalität verwendet. Mit dem korrekten Verlauf der RC-Kurve werden die unerwünschten Signale gefiltert und das auszuwertende Signal weitergeleitet. Im Folgenden werden die beiden Signale getrennt betrachtet.

Verstärkung des Senders

Prinzip des Moduls

Abb.7 Sendesignallaufprinzip

Mehrere kurz aufeinander folgende Impulse gewährleisten ein ausreichendes Aufladen des Kondensators. Da das FPGA aber nur mit 3,3 V und kleinen Strömen arbeitet, werden die Impulse mit Transistoren verstärkt um die Sendekapsel ausreichend versorgen zu können.



Realisierung im Schaltplan

Abb.8 Verstärkerschaltplan für Ultraschallsender
Abb.9 Großsignalersatzschaltbild zu Abb.8

Es werden pro Entfernungsmessung sieben Sendeimpulse vom FPGA geliefert und mit den beiden Transistoren T1 und Q1 verstärkt. Damit ist gewährleistet, dass die Intensität ausreicht um die Senderkapsel zum Senden zu bewegen. Außerdem wird der Kondensator C1 geladen. Weil nur Impulse verstärkt werden, können die Transistoren im Sättigungsbereich betrieben werden, um die größtmögliche Verstärkung zu erreichen. Nachdem aus dem Datenblatt der Transistoren die Stromverstärkungsfaktoren entnommen sind, wird der Basisstrom so dimensioniert, dass die Transistoren im übersteuerten Bereich arbeiten. Es hat sich gezeigt, dass durch die Diffusionskapazitäten der Transistoren jeder Impuls verlängert wird. Um diesen Effekt zu verringern, werden die Transistoren nicht zu weit im Sättigungsbereich betrieben.












Verstärkung des Empfängers

Prinzip des Moduls

Abb.10 Empfangssignallaufprinzip

Erste Probemessungen an der Empfängerkapsel zeigen am Oszilloskop nur sehr geringe Ausschläge. Da es während der Signalverarbeitung zum Rauschen durch besonders hochohmige Widerstände innerhalb der Schaltung kommt, wird das Signal verstärkt um es in einen Spannungsbereich zu bringen, der sich deutlich von ungewollten Nebeneffekten abhebt. Zur Veranschaulichung einer weiteren Variante zur Verstärkung, wird am Empfänger ein Operationsverstärker, statt eines einfachen Transistors, verwendet.



Realisierung im Schaltplan

Abb.11 Verstärkerschaltplan für Ultraschallempfänger

Trotz dem optimalisierten Sender-Empfangssystem mit gleicher Resonanzfrequenz von 40 kHz muss das nach der Reflexion des Ultraschalls nur schwache Echo verstärkt werden, um weiterverarbeitet werden zu können.

Die Ersatzschaltbilder von Ultraschallsender und –empfänger sind identisch. Die Stromquelle des Senders bleibt jedoch auf Null, während die des Empfängers bei Empfang aktiv wird. Um Störungen durch Rauschen am hohen Innenwiderstand der Ultraschallkapsel zu vermeiden, wird an beiden Anschlüssen des Empfängers das gleiche Potential angelegt.

Der Operationsverstärker IC1A dient als Vorverstärker und Filter. In dieser invertierenden Beschaltung verstärkt er die Eingangssignale um das zehnfache und filtert alle Schwingungen ab 48 kHz. heraus. Um die empfangenen Signale weiterzugeben und gleichzeitig jeden Gleichanteil abzutrennen wird der Kondensator C3 eingesetzt.

Die zweite Stufe mit IC1B ist ebenfalls als invertierender Verstärker aufgebaut und kann erneut um Faktor zehn verstärken. Dies läst sich über das Potentiometer R12 stufenlos einstellen. Zudem lässt sich der Gleichanteil mit R14 in geringen Bereichen um VCC/2 variieren, um die Empfangskurve exakt mit der RC-Kurve abzugleichen. Das Audio-Signal am Ausgang des Operationsverstärkers IC1B, schwingt um nahezu dasselbe Potential, wie das Signal am nichtinvertierenden Eingang.

Erzeugung einer RC-Kurve zur Filterung

Prinzip des Moduls

Abb.12 Prinzip der Signalfilterung

Aus der Richtcharakteristik ist zu entnehmen, wie stark der Ultraschall neben der Hauptrichtung auch in andere Richtungen abstrahlt. Auf ähnliche Weise empfängt auch der Empfänger aus dem gesamten Raum Signale. Da Sender- und Empfängerkapsel dicht nebeneinander verbaut sind und der ausgesendete Schall nicht nur durch Reflexion zum Empfänger gelangt, sondern auch auf direktem Wege durch seitliche Abstrahlung während der Messung, ist es notwendig die bei der Sendung seitlich abgestrahlten Impulse herauszufiltern. Das wird durch den Vergleich mit einer RC-Entladungskurve erreicht. Während die Senderkapsel die Impulse erhält, wird parallel dazu ein Kondensator aufgeladen. Ist der Sendevorgang abgeschlossen, entlädt sich dieser Kondensator über einen Widerstand. In einem Operationsverstärker wird diese Entladekurve mit dem Signal des verstärkten Ultraschalleingangs verglichen. Seitlich emittierter Ultraschall fällt beim Empfangen unter die RC-Kurve und wird dadurch nicht verwertet. Beim Auftreffen des senkrecht reflektierten Schalls ist die RC-Kurve ausreichend abgefallen um einer komplikationslosen Messung nicht mehr im Wege zu stehen.


Realisierung im Schaltplan

Abb.13 Schaltplan zur Signalfilterung

Der Fluss der Ladung in den Kondensator legt die Spannungserhöhung gegenüber der anderen Kondensatorplatte fest. Wie viel Ladung in den Kondensator fließt wird mit dem Potentiometer R5 eingestellt. Das Potential an der unteren Kondensatorseite liegt bei der halben Betriebsspannung. Beim Entladevorgang, also nach den 7 Sendeimpulsen, wird die erhöhte Ladungsansammlung auf der oberen Kondensatorplatte über den Widerstand R6 zur unteren Platte geleitet. Die Diode D1 verhindert ein zusätzliches Entladen durch R4 und den Ultraschallsender. Da der Eingangswiderstand des Operationsverstärkers sehr groß ist, findet auch darüber kaum eine Entladung statt. Dadurch ergibt sich eine typische Entladekurve mit der Zeitkonstante τ=R6*C1. Diese Kurve nähert sich asymptotisch der halben Betriebsspannung an. Der Operationsverstärker IC2A dient als Komparator zwischen RC-Kurve und dem Audio-Signal. Sobald das Potential des Audio-Singals höher ist als das der RC-Kurve, schaltet der Ausgang nahezu auf Betriebsspannung.



Anpassung der Spannung für das FPGA

Prinzip des Moduls

Abb.14 Prinzip Pegelanpassung

Da das FPGA im CMOS-Pegel von 0 – 3,3 V arbeitet und im Normalfall eine höhere Spannung am Ausgang es Komparators anliegt, ist eine Reduzierung der Spannung nötig. Eine parallel zum FPGA - Eingang geschaltete Z-Diode reduziert die Spannung auf die gewünschten 3,3 V.







Realisierung im Schaltplan

Abb.15 Schaltplan für Spannungspegelanpassung an FPGA

Die Spannung am FPGA muss auf 3,3 V reguliert werden. Deshalb wird das Ausgabepotential des Operationsverstärkers verwendet, um einen PNP- Transistor zu schalten. Der Operationsverstärker IC2A kann nicht bis zur oberen und unteren Betriebsspannung (0V und VCC) aussteuern. Hat der Operationsverstärker auf maximales positives Potential geschalten, kann der Transistor BC328 noch teilweise Strom durchlassen. Um den Transistor sicher zu sperren, wird mit dem Widerstand R16 das Potential auf nahezu VCC gebracht. Der andere Fall, dass der Operationsverstärker gegen GND schaltet, veranlasst das Öffnen des PNP-Transistors und lässt damit genügend Strom durch die Zener-Diode fließen, welche das Potential am FPGA_EINGANG auf 3,3V beschränkt.







Gesamter Schaltplan und Aufbau

Abb.16 Schaltplan der kompletter Signalaufbereitung
Abb.18 Layout (Platinenrückseite)
Abb.17 Aufbau
Abb.19 Bestückungsplan






















Hardwarebeschreibungssprache VHDL

VHDL Einleitung

VHDL ist eine hardwarebeschreibende Sprache. Damit wird dem FPGA vorgegeben, welche Verkettung der CMOS Bauteile freigegeben wird um die in VHDL eingegebenen Befehle in Hardware umzusetzen. Alle Signaldurchläufe durch das FPGA werden parallel ausgeführt, das macht das FPGA sehr leistungsstark. Es ist jedoch auch möglich Prozesse mit sequenzieller Struktur in VHDL zu realisieren. In unserem Fall wurden beide Arten der Signallaufstrukur gewählt. Um verschiedene externe Signale miteinander zu verbinden, werden interne Signale definiert.

VHDL Moduleinteilung

Ein komplettes VHDL-Programm setzt sich aus einzelnen Modulen zusammen, welche miteinander verknüpft sind. Diese Art von Programm ist für Teamarbeiten sehr gut geeignet, da die Aufteilung von Modulen an verschiedene Entwickler einfach möglich ist. Ein besonderes Augenmerk sollte dabei auf die Festlegung der Schnittstellen und Übergabewerte gelegt werden. Für das Ultraschallprojekt wurden die Module wie folgt festgelegt:

Abb.20 VHDL Modulaufteilungsplan

Die externen Signale sind blau markiert und wurden schon beschrieben.

VHDL Modulschnitstellen

Signalart Eigenschaft
clk2 10Bit-Block, STD_LOGIC_VECTOR Zählt mit 25MHz hoch bis „1011011000“ und wirdanschließend auf „0000000000“ zurückgesetzt
startzähler 11Bit-Block, STD_LOGIC_VECTOR Zählt für Schallgeschwindigkeit alle 5mm um eine Stelle hoch
einaus 4Bit-Block, STD_LOGIC_VECTOR Enthält die Flankenwechsel der Ultraschallimpulse
sender_ein 1Bit-Wert, STD_LOGIC Wenn 1 dann soll der Ultraschallsender die 7 Sendeimpulse bekommen
wegzähler1 10Bit-Block, STD_LOGIC_VECTOR Zählt nach Offsetkorrektur für Schallgeschwindigkeit in 1 cm Schritten
mm 1Bit-Wert, STD_LOGIC Wechselt für Schallgeschwindigkeit in 5mm Schritten seinen Wert
seg1 - seg4 jeweils 8Bit-Wert, STD_LOGIC_VECTOR Gibt den BCD-Wert jeder Anzeigestelle an; seg1 für Meter, seg2 für Dezimeter, seg3 für Zentimeter

VHDL-CODE

----------------------------------------------------------------------------------
-- Company:                             FH-Regensburg	
-- Azubi-Engineer:                      Thomas Eichstetter	
-- 
-- Create Date:                         2011-06-28
-- Design Name: 		
-- Module Name:                         ultraschall_1.1 
-- Project Name: 
-- Target Devices: Spartan 3
-- Tool versions: 
-- Description:             Mittels Ultraschallimpuls und Laufzeitmessung über Reflexion
--                          wird die Entfernung zu einem Objekt bestimmt
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity ultraschall is
   Port (  clk :                         IN  std_logic;
           stopp :                       IN  std_logic;
           ultraschall :                 OUT  std_logic;
           lampe :                       OUT  std_logic;
           seg1 :                        out  STD_LOGIC_VECTOR (7 downto 0);
           seg2 :                        out  STD_LOGIC_VECTOR (7 downto 0);
           seg3 :                        out  STD_LOGIC_VECTOR (7 downto 0);
           seg4 :                        out  STD_LOGIC_VECTOR (7 downto 0));
end ultraschall;

architecture Behavioral of ultraschall is

signal wegzaehler1 :                     STD_LOGIC_VECTOR (9 downto 0) :="0000000000";
signal senderein :                       STD_LOGIC := '0';
signal ultra :                           STD_LOGIC_VECTOR (9 downto 0) :="0000000000";
signal einaus:                           STD_LOGIC_VECTOR (3 downto 0) :="0000";
signal startzaehler :                    STD_LOGIC_VECTOR (10 downto 0) :="00000000000";
signal clk2 :                            STD_LOGIC_VECTOR (11 downto 0) := "000000000000";
signal fivemm :                          STD_LOGIC_VECTOR (11 downto 0) := "000000000000";
signal mm:                               STD_LOGIC := '0';
signal flag:                             STD_LOGIC := '0';

begin


lampe <= not stopp;
ultraschall <=  einaus(0);


process ( clk)                              --Timer wird auf 5mm Weg/Periode gesetzt """"Zähler1""""
begin
if clk'event and clk='1' then	

    clk2 <= clk2+1;                         --clk2 Zähl-Periode jetzt auf 50MHz	 
    if (clk2=728) then                      --auf 5mm einstellen: 0,005m * 50e6 Hz/ (343 m/s) = 729
        
        clk2 <= "000000000000";             --doppelter Laufweg noch nicht berücksichtigt

    end if;                                 --und 1011011000=728 weil er von 0 anfängt zu zählen

end if;
end process;



process ( clk )	                            --Ultraschallimpuls wird erzeugt (7 Impulse bei 40kHz)""""Zähler2""""
begin
if clk'event and clk='1' then

    if einaus >= 14 then                    --14 da HIGH und LOW gezählt werden

        senderein <= '0';
    
    end if;
			
    
    if clk2 = 728 then

        startzaehler <= startzaehler+1;     --Zähler der jeweils in 5mm-Steps zählt
    
    end if;

    if (startzaehler=2047) then  --Periode der Messung (ca 30ms)

        startzaehler <= "00000000000";

        senderein <= '1';

    end if;

end if;
end process;


process ( clk )
begin
if clk'event and clk='0' then

    if (senderein = '1' ) then

        ultra <= ultra+1;

        if (ultra=625) then            -- 50MHz/40kHz/2= 625 Takte [2mal wegen ein/aus für Ultraschallkapsel 40kHz]

            einaus <= einaus + 1;      -- hier auch wirklich 625 Takte, weil er danach sofort eins dazuzählt

            ultra <="0000000000";

        end if;

        if einaus = 14 then            -- Rücksetzten

            einaus <= "0000";

        end if;
    end if;

end if;
end process;



process (clk)

begin
if clk'event and clk='1' then

    if (startzaehler=8) then           -- setzt alle ~30ms Zähler auf 0 zurück,1110 zusätzlich Trägheitsausgleich der Senderkapsel (offset)

        fivemm <= "000000000000";      -- muss angepasst werden auf die jeweilige Spannung

    end if;

    if (clk2 = 0) then                 -- erhöht jeden bestimmten Zeitabschnitt um 5mm

        fivemm <= fivemm + 1;	       -- eigentliche Wegzählung

    end if;
		
    if (senderein='1') then            -- Bereit machen für Wertänderung

        flag <= '1';                   -- zeigt das Ultraschallimpuls unterwegs ist

    end if;


    if (stopp='1'  and flag='1') then                            --Wertänderung der zuletzt gemessenen Länge
        if (fivemm(10 downto 2) < 500) then                      -- Zu weit weg -> alter Wert bleibt
            if (fivemm(10 downto 2) > 2) then                    -- Zu nah dran -> alter Wert bleibt
                wegzaehler1(8 downto 0) <= fivemm(10 downto 2);  -- geteilt durch 2 wegen hin/zurück und 5mm extra
                mm <= fivemm(1);                                 -- 5mm
 
               wegzaehler1(9) <='0';
                flag <= '0';                                     -- Impuls angekommen
            end if;

        end if;
    end if;


    if (fivemm=4095) then
        fivemm <= "000000000000";
        wegzaehler1(8 downto 0) <="111111111";

    end if;

end if;			
end process;


PROCESS ( wegzaehler1 , mm)

variable wegzaehler2 :    STD_LOGIC_VECTOR (9 downto 0) := "0000000000";

variable wegzaehler3 :    STD_LOGIC_VECTOR (9 downto 0) := "0000000000";

variable m , dm , cm :    STD_LOGIC_VECTOR (3 downto 0) := "0000";



BEGIN


wegzaehler2 := "1111111111";

wegzaehler3 := "1111111111";

m := "0000";

dm := "0000";

cm := "0000";


--Meterberechnung
if ((wegzaehler1(8 downto 0) > 399) and (wegzaehler1(8 downto 0) < 500)) then

    m := "0100";

    wegzaehler2:= wegzaehler1 - 400;		

elsif ((wegzaehler1(8 downto 0) > 299) and (wegzaehler1(8 downto 0) < 400)) then

    m := "0011";

    wegzaehler2 := wegzaehler1 - 300;

elsif ((wegzaehler1(8 downto 0) > 199) and (wegzaehler1(8 downto 0) < 300)) then

    m := "0010";

    wegzaehler2 := wegzaehler1 - 200;

elsif ((wegzaehler1(8 downto 0) > 99) and (wegzaehler1(8 downto 0) < 200)) then

    m := "0001";

    wegzaehler2 := wegzaehler1 - 100;

elsif (wegzaehler1(8 downto 0) < 100) then

    m := "0000";

    wegzaehler2 := wegzaehler1;

else 
    m := "1111";
    wegzaehler2 := "1111111111";

end if;



--Dezimeterberechnung
if ((wegzaehler2(8 downto 0) > 89)and(wegzaehler2(8 downto 0) < 100)) then

    dm := "1001";

    wegzaehler3 := wegzaehler2 -90;

elsif ((wegzaehler2(8 downto 0) > 79)and(wegzaehler2(8 downto 0) < 90)) then

    dm := "1000";

    wegzaehler3 := wegzaehler2 -80;
elsif ((wegzaehler2(8 downto 0) > 69)and(wegzaehler2(8 downto 0) < 80)) then

    dm := "0111";

    wegzaehler3 := wegzaehler2 -70;

elsif ((wegzaehler2(8 downto 0) > 59)and(wegzaehler2(8 downto 0) < 70)) then

    dm := "0110";

    wegzaehler3 := wegzaehler2 -60;

elsif ((wegzaehler2(8 downto 0) > 49)and(wegzaehler2(8 downto 0) < 60)) then

    dm := "0101";

    wegzaehler3 := wegzaehler2 -50;

elsif ((wegzaehler2(8 downto 0) > 39)and(wegzaehler2(8 downto 0) < 50)) then

    dm := "0100";

    wegzaehler3 := wegzaehler2 -40;

elsif ((wegzaehler2(8 downto 0) > 29)and(wegzaehler2(8 downto 0) < 40)) then

    dm := "0011";

    wegzaehler3 := wegzaehler2 -30;

elsif ((wegzaehler2(8 downto 0) > 19)and(wegzaehler2(8 downto 0) < 30)) then

    dm := "0010";

    wegzaehler3 := wegzaehler2 -20;

elsif ((wegzaehler2(8 downto 0) > 9)and(wegzaehler2(8 downto 0) < 20)) then

    dm := "0001";

    wegzaehler3 := wegzaehler2 -10;

elsif (wegzaehler2(8 downto 0) < 10) then

    dm := "0000";

    wegzaehler3 := wegzaehler2;

else
    dm := "1111";

    wegzaehler3 := "1111111111";

end if;



--Zentimeterberechnung
if (wegzaehler3 < 10) then

    cm := wegzaehler3(3 downto 0);

else 
    cm := "1111";

end if;


--Millimeterberechnung				
CASE mm IS
    WHEN '0'    => seg4 <= "00111111";
    WHEN OTHERS => seg4 <= "01101101";
END CASE;	
					

if (cm="1111") then   --falls Falscher Wert mm auf nichts
    seg4 <="00000000";
end if;
				
CASE cm IS
    WHEN "0000" =>      seg3 <= "00111111";
    WHEN "0001" =>      seg3 <= "00000110";
    WHEN "0010" =>      seg3 <= "01011011";
    WHEN "0011" =>      seg3 <= "01001111";
    WHEN "0100" =>      seg3 <= "01100110";
    WHEN "0101" =>      seg3 <= "01101101";
    WHEN "0110" =>      seg3 <= "01111101";
    WHEN "0111" =>      seg3 <= "00000111";
    WHEN "1000" =>      seg3 <= "01111111";
    WHEN "1001" =>      seg3 <= "01101111";
    WHEN OTHERS =>      seg3 <= "00000000";		
END CASE;
		  
CASE dm IS
    WHEN "0000" =>      seg2 <= "00111111";
    WHEN "0001" =>      seg2 <= "00000110";
    WHEN "0010" =>      seg2 <= "01011011";
    WHEN "0011" =>      seg2 <= "01001111";
    WHEN "0100" =>      seg2 <= "01100110";
    WHEN "0101" =>      seg2 <= "01101101";
    WHEN "0110" =>      seg2 <= "01111101";
    WHEN "0111" =>      seg2 <= "00000111";
    WHEN "1000" =>      seg2 <= "01111111";
    WHEN "1001" =>      seg2 <= "01101111";
    WHEN OTHERS =>      seg2 <= "00000000";
END CASE;
			
CASE m IS
    WHEN "0000" =>      seg1 <= "10111111";
    WHEN "0001" =>      seg1 <= "10000110";
    WHEN "0010" =>      seg1 <= "11011011";
    WHEN "0011" =>      seg1 <= "11001111";
    WHEN "0100" =>      seg1 <= "11100110";
    WHEN "0101" =>      seg1 <= "11101101";
    WHEN "0110" =>      seg1 <= "11111101";
    WHEN "0111" =>      seg1 <= "10000111";
    WHEN "1000" =>      seg1 <= "11111111";
    WHEN "1001" =>      seg1 <= "11101111";
    WHEN OTHERS =>      seg1 <= "00000000";
END CASE;	
					
	
END PROCESS ;
-------------------------------------------------------------------------
end Behavioral;

Pinbelegung

Abb.21 Anschluss am FPGA-Board
Abb.22 Anschluss an der Signalverarbeitung

NET "clk" LOC = AA12;
NET "seg1[0]" LOC = E15;
NET "seg1[1]" LOC = E16;
NET "seg1[2]" LOC = A14;
NET "seg1[3]" LOC = D14;
NET "seg1[4]" LOC = D13;
NET "seg1[5]" LOC = B13;
NET "seg1[6]" LOC = E13;
NET "seg1[7]" LOC = D15;
NET "seg2[0]" LOC = B17;
NET "seg2[1]" LOC = B18;
NET "seg2[2]" LOC = A18;
NET "seg2[3]" LOC = B15;
NET "seg2[4]" LOC = D17;
NET "seg2[5]" LOC = C17;
NET "seg2[6]" LOC = E17;
NET "seg2[7]" LOC = A19;
NET "seg3[0]" LOC = D19;
NET "seg3[1]" LOC = F18;
NET "seg3[2]" LOC = C20;
NET "seg3[3]" LOC = C19;
NET "seg3[4]" LOC = C18;
NET "seg3[5]" LOC = B19;
NET "seg3[6]" LOC = D18;
NET "seg3[7]" LOC = F17;
NET "seg4[0]" LOC = F19;
NET "seg4[1]" LOC = G17;
NET "seg4[2]" LOC = E19;
NET "seg4[3]" LOC = D21;
NET "seg4[4]" LOC = D20;
NET "seg4[5]" LOC = E18;
NET "seg4[6]" LOC = C22;
NET "stopp" LOC = V10;
NET "seg4[7]" LOC = E20;
NET "ultraschall" LOC = AB13;
NET "lampe" LOC = W2;

Funktionstest

Natürlich ist es am einfachsten die Einstellung des Ultraschallsenders mit dem Oszilloskop nachzuvollziehen. Diese Anleitung soll aber vor allem dazu dienen, den Leuten eine Inbetriebnahme zu ermöglichen, die kein Oszilloskop zur Hand haben.

Ganz allgemein ist jedem anzuraten, der Geräte neu einstellen will, wie auch bei der Modulentwicklung eine Reihenfolge zu verfolgen und Schritt für Schritt vorzugehen. Zur Vorbereitung sollten die Sensoren einigermaßen frei liegen und in ca. 30 cm Abstand ein flacher, parallel zu den Sensoren liegende Fläche stehen. Zu Anfang alle drei Potentiometer gegen den Uhrzeigersinn auf Anschlag drehen. Anschließend wird die Quelle (Netzgerät oder Batterien sind möglich) angeschlossen. Um die Bauteile nicht zu stark zu belasten und sie damit zu zerstören, ist eine Spannung von 5-20 V empfehlenswert. In der Testphase wurden 10 V verwendet, damit der Ultraschallimpuls ausreichend stark war.

Die Potentiale am Eingang des Verstärkers IC2A liegen nah beieinander. Deshalb verändert man das Potentiometer R14 so lange, bis das FPGA das erste Mal einen Wert anzeigt. Damit ist der Offset des Signals knapp unterhalb des Spannungsendwertes der RC-Kurve. Vorsicht: Bitte darauf achten, dass man nicht zu weit dreht, denn das System ist diesbezüglich sehr empfindlich und größere Entfernungen nicht mehr einwandfrei gemessen werden können.

Dann Poti R5 langsam im Uhrzeigersinn drehen, bis der zu erwartende Messwert stabil angezeigt wird. Nun sollte der Ultraschallentfernungsmesser eingestellt sein um Entfernung messen zu können. Jetzt kann der Ultraschallentfernungsmesser auf ein zu messendes Objekt ausgerichtet werden. Mit R12 lässt sich die Verstärkung von um Faktor 10 variieren. Das ermöglicht es Hindernisse, welche neben der Messstrecke sind und schwache Signale zurücklaufen lassen, auszublenden.


Fazit

Dieses Projekt der Ultraschallentfernungsmessung eignet sich hervorragend um verschiedene Grundschaltungen innerhalb eines Netzwerkes besser zu verstehen. Auch erste Schritte mit VHDL sind hiermit leicht zu realisieren. Erfolge sind bereits während dem Projekt nach den einzelnen Abschnitten zu erkennen. Durch die 7-Segment-Anzeigen ist die Funktionalität auch für Anfänger leicht ersichtlich und der Ultraschallentfernungsmesser eignet sich deshalb hervorragend als Vorführprojekt. Die Entfernungsmessung funktioniert bis zu 4 m zuverlässig.


Siehe auch