Elektroda.pl
Elektroda.pl
X
PCBway
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Vhdl-sterowanie szerością impulsu

03 Gru 2011 14:35 2676 7
  • Poziom 8  
    Mam za zadanie napisania programu który będzie sterował serwomechanizmem metodą PWM.
    Odpowiedniemu położeniu serwomechanizmu odpowiada sygnał o konkretnym wypełnieniu. Oto mój pierwszy program "testowy" za pomocą którego chcę po prostu ruszyć tym silniczkiem.

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    ---- Uncomment the following library declaration if instantiating
    ---- any Xilinx primitives in this code.
    --library UNISIM;
    --use UNISIM.VComponents.all;

    entity Robot is
    port(
    clk_50Hz,a,b,c:in std_logic;
    wyj:out std_logic
    );
    end Robot;

    architecture Behavioral of Robot is

    begin

    process(a)
    variable x :integer range 0 to 50000000;
    begin
    if(clk_50Hz'event and clk_50Hz = '1') then
    x:=x+1;
    if (x<30000) then
    wyj<='1';
    end if;
    if (x>30000) then
    wyj<='0';
    end if;
    if(x>1000000) then
    x:=0;
    end if;
    end if;
    end process;

    process(b)
    variable x0 :integer range 0 to 50000000;
    begin
    if(clk_50Hz'event and clk_50Hz = '1') then
    x0:=x0+1;
    if (x0<75000) then
    wyj<='1';
    end if;
    if (x0>75000) then
    wyj<='0';
    end if;
    if(x0>=1000000) then
    x0:=0;
    end if;
    end if;
    end process;


    process(c)
    variable x1:integer range 0 to 50000000;
    begin
    if(clk_50Hz'event and clk_50Hz = '1') then
    x1:=x1+1;
    if (x1<125000) then
    wyj<='1';
    end if;
    if (x1>125000) then
    wyj<='0';
    end if;
    if(x1>1000000) then
    x1:=0;
    end if;
    end if;
    end process;

    end Behavioral;


    Wejścia a,b,c to sygnały wejściowe za pomocą których dobieram wypełnienie, a więc położenie serwomechanizmu. Szerokość impulsu trwa 1000000 impulsów taktowania układu FPGA. A zmienne 30000, 750000 oraz 125000 odpowiadają konkretnemu wypełnieniu.
    Jednak nie wiem dlaczego mam podobny błąd w trakcie kompilacji :
    ERROR:Xst:528 - Multi-source in Unit <Robot> on signal <wyj>

    Byłbym wdzięczny za wskazówkę skąd jest ten błąd i ewentualne sugestie w celu lepszego działania programu.
  • PCBway
  • Poziom 38  
    m1szza napisał:

    Jednak nie wiem dlaczego mam podobny błąd w trakcie kompilacji :
    Code:
    ERROR:Xst:528 - Multi-source in Unit <Robot> on signal <wyj>

    Trzy konkurencyjne procesy próbują sterować jedną linią.
    Wydaje mi się, że wiem co chcesz zrobić i droga jaką chcesz to osiągnąć jest błędna. Zauważ, że masz trzy konkurencyjne procesy gdzie w ogóle nie wykorzystujesz sygnałów a, b i c. Zatem w jakim celu stworzyłeś te procesy?
  • PCBway
  • Pomocny post
    Poziom 30  
    m1szza napisał:
    Mam za zadanie napisania programu który będzie sterował serwomechanizmem metodą PWM.
    Odpowiedniemu położeniu serwomechanizmu odpowiada sygnał o konkretnym wypełnieniu. Oto mój pierwszy program "testowy" za pomocą którego chcę po prostu ruszyć tym silniczkiem.


    Prescaler + Timer + rejestr compare TOP + rejestr compare Toggle + bufor na niego. Z takich klocków powinieneś złożyć taki IP Core PWM.

    Prescaler na timer, jeden compare TOP, który zresetuje licznik (częstotliwość), oraz N-compare z N-buforami do niego (wypełnienie), wtedy masz N dowolną ilość sygnałów PWM. Bufory są potrzebne, żeby zapobiec skokowi wypełnieniu. Aktualizacja, np. przy resecie licznika.

    Zmianę stanu możesz zrobić za pomocą zatrzasku set-reset. Z sygnału compare Toggle ustaw na '0', reset licznika na '1'.

    Teraz składnia:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Powtórzę to N lub N-1 jeden razy, to nie jest język programowania ! Tylko opis sprzętu. W każdym procesie, tworzysz integer range 0 to 50000000, co daje lekko 26 przerzutników*3, w dodatku przypisujesz irracjonalnie wielką logikę kombinacyjną stosując takie porównania > i <, mniejsze zło jest kiedy sprawdza się wielokrotność 2 (bo wtedy znaczenie ma tylko jeden bit). W VHDLu jest if-elsif-else-end if. Tak samo lepiej jest stosować, STD_LOGIC_VECTOR, a nie integer. Niektóre symulatory mogą być za głupie, żeby skojarzyć ograniczony zakres integer do 2^(N-1) przerzutników i w razie czego go przekręcić. Prędzej może się wysypać, tak mówię żeby się nie dziwił między wynikiem symulacji, a działaniem układu. Natomiast STD_LOGIC_VECTOR oddaje całe piękno sprzętu.

    Więc tak, zakładając że 16-bitowa rozdzielczość Ci wystarczy (więcej nie ma sensu, wskazane będzie może mniejsza ilość). Jeden 16-bitowy prescaler (lub mniejszy, gdzie zegar będzie wyprowadzony z bitu prescalera), jeden 16-bitowy (lub mniejsz) licznik, jeden komparator (znak "=", a nie < >) do resetu, 3 komparatory ("=") dla wypełnianie, 3*buforek (jeśli będzie przewidziana zmiana wypełnienia), 3*set-reset. I taki opis HDL, oddaje pełną semantykę sprzętu.

    m1szza napisał:
    Jednak nie wiem dlaczego mam podobny błąd w trakcie kompilacji :
    ERROR:Xst:528 - Multi-source in Unit <Robot> on signal <wyj>

    Sygnały wejściowe a, b oraz c, wcale ich nie używasz (powinień być warning, żółta kartka). Każdy proces jest w części współbieżnej, więc nie można zastosować kilka procesów sterujących jednym sygnałem. Wyobraź Sobie, że masz jeden kabel wyjściowy, a w pudełeczku łączą się w jednym punkcie 3 kabelki wejściowe. Jeśli na dwóch wejściowych jednocześnie będzie gnd oraz vdd, to co będzie na wyjściu ? Raczej pudełeczko zrobi KaBumm...

    Kompilacje to można zrobić Sobie na poziomie bibliotek, tu robisz syntezę.

    Używaj wcięć oraz znacznika syntax ! I staraj się trzymać jakąś konwencję nazw oraz zmiennych. Poczytaj "Code Complete 2" Steve McConnell, może dotyczy to normalnych języków programowania, ale to będzie dobra lektura na temat Savoir Vivre kodu. Bo takie cuda jak a, b, c, x, brak etykiet dla procesów, nie wiele mówią. A opis/kod powinno się czytać jak przyjemną lekturę przy kominku z whisky, a nie taki bazgroł, który powinnień wylądować w koszu.
  • Poziom 8  
    Cytat:
    Wydaje mi się, że wiem co chcesz zrobić i droga jaką chcesz to osiągnąć jest błędna. Zauważ, że masz trzy konkurencyjne procesy gdzie w ogóle nie wykorzystujesz sygnałów a, b i c. Zatem w jakim celu stworzyłeś te procesy?

    Wykorzystuje, po prostu w momencie jak wciskam swicha oznakowanego jako a,b lub c włącza się dany proces.
    Cytat:
    Powtórzę to N lub N-1 jeden razy, to nie jest język programowania !

    Do tej pory pisałem w c i asm, z tego co słyszałem to asm jest podobny swą logiką do VHDL-u, stąd moje możliwe że i błędne rozumowanie, a literatura nie wyczerpuje realnej pracy na sprzęcie.
    Cytat:
    Sygnały wejściowe a, b oraz c, wcale ich nie używasz (powinień być warning, żółta kartka).

    No tak, bo służą one tylko do pobudzenia procesu(czy to tak nie działa?), warrningi oczywiście są.
    Cytat:
    Każdy proces jest w części współbieżnej, więc nie można zastosować kilka procesów sterujących jednym sygnałem.

    Czyli nie mogę wykorzystać tego samego wyjścia w oddzielnych procesach? Nawet jeżeli na siebie by wyjścia nie nachodziły. Jest to ogólna zasada programowania w VHDL-u?
    Cytat:
    ]Używaj wcięć oraz znacznika syntax ! I staraj się trzymać jakąś konwencję nazw oraz zmiennych. Poczytaj "Code Complete 2" Steve McConnell, może dotyczy to normalnych języków programowania, ale to będzie dobra lektura na temat Savoir Vivre kodu. Bo takie cuda jak a, b, c, x, brak etykiet dla procesów, nie wiele mówią. A opis/kod powinno się czytać jak przyjemną lekturę przy kominku z whisky, a nie taki bazgroł, który powinnień wylądować w koszu.

    Dostosuje się do rady :).

    I jeszcze jedno czy Plescaler to po prostu kwarc?
  • Poziom 30  
    m1szza napisał:
    Do tej pory pisałem w c i asm, z tego co słyszałem to asm jest podobny swą logiką do VHDL-u, stąd moje możliwe że i błędne rozumowanie, a literatura nie wyczerpuje realnej pracy na sprzęcie.

    ASM czy C, to języki liniowe, bazujące na danych i instrukcjach. Kod wykonuje się liniowo z góry na dół, z możliwością odwołania/skoku, gdzie indziej, ale nadal liniowo. Natomiast HDL, służy do opisu zachowań i połączenia między logiką (bramki, przerzutniki). Czyli tworzysz sprzęt, który może wykonywać się współbieżnie, synchronicznie oraz asynchronicznie niezależnie/zależnie od innej części logiki, ponieważ operujesz nie na instrukcjach/danych tylko na sygnale ('0'/'1'). Gdzie ten sygnał jest zależny od opisu Twojej logiki. Innymi słowy, takie "cuś" niewiele się różni od projektu wykonywanego na bazie układzików TTL/CMOS, ale z możliwością upchania w jeden układ PLD/ASIC :)

    m1szza napisał:
    No tak, bo służą one tylko do pobudzenia procesu(czy to tak nie działa?), warrningi oczywiście są.

    Teoretycznie to tak, do tego służy lista czułości. Problem jest w tym, że sygnał z grupy std_logic, ma kilkanaście stanów ('X', 'U', 'L', '1', '0', ...). Więc syntezerowi sprawiasz wielką przykrość, bo dla niego ważna jest logika boolowska. I nie ma chęci ani możliwości rozpatrywać wszystkiego, więc bardziej elegancko przyzwoicie wygląda coś takiego:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Wtedy wiadomo, z czym ma się doczynienia. Czyli stwórz układ kombinacyjny, który reaguje na poziom logiczny s_button1. Przyciski, musisz przepuścić przez tzw. debouncer, czyli układ który pozbędzie się niemiłych przeskoków w czasie wciskanie buttona. Tak, żeby faktycznie jedno wciśnięcie oznaczało jedną akcję. Najprostsza wersja, kilka przerzutników w układzie SIPO (szeregowe wejście - równoległe wyjście) z logiką detekcji. I później wykrywanie zbocza i strobowanie tego sygnału (jeden cykl zegara) i za pomocą prostego if w układzie synchronicznym wykryjesz faktyczne JEDNO wciśnięcie.
    m1szza napisał:
    Czyli nie mogę wykorzystać tego samego wyjścia w oddzielnych procesach? Nawet jeżeli na siebie by wyjścia nie nachodziły. Jest to ogólna zasada programowania w VHDL-u?

    Nie możesz operować na tym samym sygnale przez części współbieżne (np. process) ! Jak chcesz w ten sposób działać, musisz dodać jakąś bramkę, ex. sygnal <=sygnal_process1 and sygnal_process2, istnieje coś takiego jak wyższa forma abstrakcji na sygnałami, co takie coś umożliwia, ale i tak sprowadzana jest potem do takiej formy co przedstawiłem (dotyczy VHLD/Verilog).
    m1szza napisał:
    I jeszcze jedno czy Plescaler to po prostu kwarc?

    Preskaler:
    Prescaler, inaczej
    Dzielnik częstotliwości

    Najprostsza forma, zwykły licznik liczący w górę. Wyprowadzasz z niego np. 2 bit, to masz częstotliwość podzieloną przez 2^(nr_bitu) = 4. Tylko uważaj, dobrą zasadą i regułą jest trzymanie się jednego sygnału zegarowego w systemie ! Oznacza to, że wszystkie procesy synchroniczne napędzasz oryginalnym zegarem, natomiast podzielonym dajesz przez np. detektor zbocza i wykrywasz takie strobowanie kombinacyjnie (czyli if strobe = '1', process synchroniczny, napędzany jednym i wspólnym oryginalnym zegarem), dzięki temu masz wrażenie, że process działa jakby clock byłby podzielony. W ten sposób unikasz wiele nieprzyjemności, jitter, clock skew i wiele różnych trudnych pojęć :P Co potrafią zburzyć cały misterny plan...

    Zajrzyj tu:
    Kompedium wiedzy na temat CPLD/FPGA
  • Poziom 8  
    Po krótkiej przerwie dopiero teraz wróciłem do tego serwomechanizmu.
    Udało mi się zrobić program za pomocą którego ustawiam położenie serwomechanizmu w wybranych konfiguracjach:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod



    Jednak jest następny problem. Powyżej przedstawiony program ustawia serwo w zadanej pozycji, jednak serwo rusza się z maksymalną prędkością aż osiągnie swoje docelowe miejsce. Chcę zmniejszyć prędkość poruszania się serwo oraz móc określić w jakim położeniu aktualnie się znajduje(w powyższym programie mam trzy docelowe pozycje, jednak mogę zatrzymać serwo puszczając swicha wejściowego przed osiągnieciem zadanej pozycji i takim sposobem mam go na innym miejscu). Próbowałem napisać program który będzie stopniowo zwiększał wypełnienie impulsu z szybkością jaką będę chciał, a dzięki temu już mógłbym ustalić jego położenie. Oto moje wypociny:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod


    Robot w ogóle się nie rusza. Nie wiem dlaczego. Proszę o pomoc.
  • Poziom 8  
    Problem został już rozwiązany, a oto przyczyna jego rozwiązania:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    end Behavioral;


    Temat zamykam.