logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega32][C]Jak "dopasować rozmiar" zmiennej?

A.T. 31 Sie 2011 10:29 2442 24
REKLAMA
  • #1 9880860
    A.T.
    Poziom 20  
    Witam
    jestem początkującym i nie wiem jak się rozwiązuje tego typy problemy. Chodzi mi o sterowanie przetwornikiem DAC MAX534. Jeśli z dotychczas napisanego programu wychodzi mi zmienna, która przyjmuje wartości z zakresu od -10000.0 do 10000.0 i jest to float to jak przy jej pomocy mam sterować tym przetwornikiem którego rozdzielczość to 8 bitów. Jeżeli to ważne to dodam, że ta zmienna wychodzi z regulatora PID, a sterować chcę poprzez ten przetwornik DAC i mostek H silnikiem.
    Dziękuję i pozdrawiam.
    A.T.
  • REKLAMA
  • #2 9880903
    tmf
    VIP Zasłużony dla elektroda
    Musisz mieć funkcję wiążącą wyjście z PID z wejściem DAC. W najprostszym przypadku, kiedy jest to zależność liniowa to z proporcji możesz to przeliczyć. Wyjdzie, że 128 odpowiada 0.0, 0 to -10000, a 255 to 10000. Z drugiej strony, skoro następuje tak znacząca redukcja, to zapewne same obliczenia w PID też można zredukować. Bo po co liczyć na float, skoro na końcu mamy 8-bitową zmienną?
  • #3 9880954
    gaskoin
    Poziom 38  
    Pokaż no ten twój PID, bo z reguły tak jak pisze tmf niepotrzebny Ci jest float.
  • #4 9880965
    A.T.
    Poziom 20  
    Dziękuję za odpowiedź. Niestety zbyt słabo rozumiem zasadę działania regulatora PID, żeby móc tam cokolwiek zmienić:/ Mam jeszcze jedno pytanie. Muszę jeszcze go nastroić. Czytałem już w Internecie jak się stroi regulatory ale że tak się wyrażę tylko na czuja. Czytałem też o jakichś metodach Zieglera Nicholsa itp ale są trochę zbyt skomplikowane:P
    Tylko, że na większości stron jest napisane, żeby stroić PID już na działającym urządzeniu. A ja zauważyłem, że jak zmienię te 3 stałe to również poziom wartości tych zmiennych wychodzących z regulatora na DAC się zmienia. Korzystając z metody proporcji musiałbym za każdym razem zmieniać tę proporcje?
    A.T.

    Dodano po 2 [minuty]:

    Tutaj jest kod regulatora. Nie jest pisany przeze mnie, tylko znaleziony w Internecie.
    Dziękuję i pozdrawiam
    A.T.

    #include <stdlib.h>
    #include <math.h>
    #include "pid.h"
    
    //-------------------------------------------------------------------------------------------------
    //
    // Definicja struktury ustawien PID - zmienna globalna
    //
    //-------------------------------------------------------------------------------------------------
    
    struct Settings_tag {
    	struct {
    		float P;
    		float I;
    		float D;
    		float angle_int_err;
    	} angle_PID;
    	
    	struct {
    		float P;
    		float I;
    		float D;
    		float diferential_int_err;
    		float diferential_old_err;
    	} diferential_PID;
    };
    struct Settings_tag settings;
    
    float phi1; // obrót pierwszego koła
    float phi2; // pbrót drugiego koła
    float dphi1; // prędkość obrotowa pierwszego koła
    float dphi2; // prędkość obrotowa drugiego koła
    
    int output1 = 0;
    int output2 = 0;
    //settings.angle_PIDa.P = 1.5;
    //settings.angle_PID.I = 10.0;
    //settings.angle_PID.D = 0.01;
    
    //-------------------------------------------------------------------------------------------------
    //
    // Procedura regulacji
    //
    //-------------------------------------------------------------------------------------------------
    
    void PID(void)
    {
    //
    //-------------------------------------------------------------------------------------------------
    // Prosty podwójny regulator PID
    //-------------------------------------------------------------------------------------------------
    //
    
    	float ster1 = 0; // sterowanie pierwszego silnika - zmienna pomocnicza
    	float ster2 = 0; // sterowanie drugiego silnika - zmienna pomocnicza
    
    	float angle_err = 0; // błąd odchylenia od pionu
    
    	float diferential_err = 0; // błąd różnicy prędkości kół
    	float diferential_deriv_err = 0; // różnica błędu różnicy prędkości kół
    
    	settings.angle_PID.P = ANGLE_PID_P; //1.5
    	settings.angle_PID.I = ANGLE_PID_I; //10.0
    	settings.angle_PID.D = ANGLE_PID_D; //0.01
    //
    ////////////////////////////////////////////////
    // Pierwszy regulator PID (odchylenie od pionu)
    //
    
    	angle_err = state.alpha; // błąd odchylenia od pionu
    	settings.angle_PID.angle_int_err += angle_err; // całkowanie błędu
    
    // Sprawdzanie granic całkowania
    
    	if(settings.angle_PID.angle_int_err > 0.1) settings.angle_PID.angle_int_err = 0.1;
    	if(settings.angle_PID.angle_int_err < -0.1) settings.angle_PID.angle_int_err = -0.1;
    
    //
    ///////////////////////////////////////////////
    // Drugi regulator PID (różnica prędkości kół)
    //
    
    	diferential_err = dphi1 - dphi2; // błąd różnicy
    	settings.diferential_PID.diferential_int_err += diferential_err; // całkowanie błędu
    
    // Sprawdzanie granic całkowania
    
    	if(settings.diferential_PID.diferential_int_err > 10) settings.diferential_PID.diferential_int_err = 10;
    	if(settings.diferential_PID.diferential_int_err < -10) settings.diferential_PID.diferential_int_err = -10;
    
    //
    
    	diferential_deriv_err = diferential_err - settings.diferential_PID.diferential_old_err; // różniczkowanie błędu
    
    //
    /////////////////////////////////////////////
    // Wyliczanie sterowania dla pierwszego koła
    //
    
    	ster1 = (angle_err * settings.angle_PID.P + state.dalpha * settings.angle_PID.D + settings.angle_PID.angle_int_err * settings.angle_PID.I)
    		+ diferential_err * settings.diferential_PID.P + settings.diferential_PID.diferential_int_err * settings.diferential_PID.I
    		+ diferential_deriv_err * settings.diferential_PID.D;
    
    //
    ///////////////////////////////////////////
    // Wyliczanie sterowania dla drugiego koła
    //
    
    	ster2 = (angle_err * settings.angle_PID.P + state.dalpha * settings.angle_PID.D + settings.angle_PID.angle_int_err * settings.angle_PID.I)
    		- diferential_err * settings.diferential_PID.P - settings.diferential_PID.diferential_int_err * settings.diferential_PID.I
    		- diferential_deriv_err * settings.diferential_PID.D;
    
    	output1 = ster1;
    	output2 = ster2;
    
    }


    Dodano po 3 [minuty]:

    Dodam jeszcze, że jest to podwójny regulator. Projektem jest robot balansujący. Czyli do regulatora wchodzi zmienna state.alpha - odchylenie od pionu oraz state.dalpha - prędkość tego odchylenia.
  • REKLAMA
  • #5 9881102
    gaskoin
    Poziom 38  
    Ło matko skąd to masz :D

    W bardzo prostej formie może to wyglądać tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Trzeba jeszcze dodać sprawdzanie granic całkowania. Możesz zmniejszać wzmocnienie Kr żeby się wstrzelić w 0-255, (albo zwiększać jak sterowanie będzie działało w zakresie np 0-10% :P). Nastawy podane są dla pewnego obiektu, w rzeczywistości musisz tam podać nastawy dla swojego.

    Dałem consty w programie bo w ARMach tak się zmienne wrzuca do flasha, w AVRach wygodniej będzie zrobić define'y :)
  • #6 9887770
    A.T.
    Poziom 20  
    Bardzo dziękuję za pomoc oraz za wrzucenie uproszczonej wersji PIDa. Niestety dalej mam problem. Nie rozumiem od czego zależą granice całkowania i jakie ja powinienem wpisać.
    Pozdrawiam
    A.T.
  • #7 9887816
    nsvinc
    Poziom 35  
    To się nazywa anti-windup i służy do tego, aby (w tym przypadku) zmienna "Int" nie osiągała zbyt wysokich wartości niwelując w ten sposób prawidłowe działanie regulatora. Najłatwiej zrobić to dwoma ifami (dolny+górny) które przytną zakres liczb jakie może przyjąć zmienna Int...
  • #8 9887870
    gaskoin
    Poziom 38  
    Aaa i jeszcze jedno - zamiast pajacować z kr, przy strojeniu (jeżeli będzie strojone Z-N albo QDR) do obliczeń za sygnał wejściowy nie podajesz napięcia tylko "kod" tego napięcia z przetwornika, wtedy nic nie trzeba przeliczać.
  • #9 9887880
    A.T.
    Poziom 20  
    Dziękuje:)
    Co się podaje na zmienne CV i SP? Nie rozumiem w którym miejscu mam wpisać moje odchylenie i prędkość odchylania:/
  • #10 9887921
    gaskoin
    Poziom 38  
    Wartość aktualną i zadaną.
  • #11 9888067
    A.T.
    Poziom 20  
    Kurcze teraz to już coraz mniej rozumiem:/
    Nie wiem czy dobrze wyjaśniłem jak to ma działać:)
    Projektem jest robot balansujący. Pobieram wartości z akcelerometru i żyroskopu. Przeliczam wartości z akcelerometru na odchylenie od pionu. I teraz te dwie informacje tzn. odchylenie i prędkość kątową wrzucam do filtra kalmana. Z filtra otrzymuję odfiltrowane odchylenie od pionu oraz prędkość tego odchylenia. I te dwie zmienne muszę podać na regulator PID, z którego otrzymuję dwie zmienne sterujące dwoma silnikami. Silnikami steruję poprzez przetwornik DAC MAX534 i mostek H sterowany prądowo.
    Dlatego teraz nie rozumiem do których zmiennych tego regulatora mam wpisać te wartości, które otrzymuję po FK? I jak mam przerobić ten kod regulatora aby dawał sygnały na 2 silniki(zmienne output1 i output2)?
    Proszę o pomoc. Sam sobie niestety nie potrafię poradzić, ponieważ tak sobie rozumiem zasadę działania regulatora PID:/
    A.T.
  • #13 9888166
    A.T.
    Poziom 20  
    Jak każdą? Przecież odchylenie jest tylko w jednej osi.
  • REKLAMA
  • #14 9889644
    LordBlick
    VIP Zasłużony dla elektroda
    Nie podałeś w sumie żadnego rysunku i myślałem, że jest to bardziej zaawansowana wersja... :)



    Tym niemniej, jeśli robisz coś w rodzaju segway-a to i tak jest jeszcze jedna oś - skręt, czyli żyroskop, sterująca proporcjami pomiędzy poszczególnymi kołami...
  • #15 9890393
    A.T.
    Poziom 20  
    Zgadza się robię coś ala segwaya. Tylko skręcać on na razie nie będzie, zależy mi tylko na tym, żeby ustał w miejscu. Bardzo proszę o odpowiedź na moje pytania, które zadałem wyżej.
    A.T.
  • #17 9890728
    A.T.
    Poziom 20  
    Dzięki za wrzucenie tego opisu regulatora. Teraz już rozumiem trochę więcej. Tylko w tym opisie autor dostawał informacje o pracy silników jedynie z enkoderów. A w moim przypadku to są także enkodery ale jeszcze głównym źródłem informacji o sterowaniu silnikami są dane o odchyleniu i szybkości tego odchylenia. W regulatorze PID, który ja tutaj wrzuciłem jest to w jakiś sposób połączone i nazwanie podwójnym regulatorem. I tego właśnie dalej nie rozumiem, jak uwzględnić dwa źródła informacji w regulatorze.
  • #19 9891559
    gaskoin
    Poziom 38  
    Widzę, że kolega to raczej by wolał dostać gotowe klocki i je sobie poskładać nieważne jak działa. Nie ma tak ! :)
  • #20 9893009
    A.T.
    Poziom 20  
    Bazując na Waszych przykładach postarałem się napisać kod regulatora PID. Na razie nie posiada on obsługi enkoderów, steruje on silnikami jedynie na podstawie danych z akcelerometru i żyroskopu - odchylenie i prędkość odchylania. Poniżej wrzucam kod, bardzo bym prosił o sprawdzenie czy w ogóle ma to szanse działać.
    Pozdrawiam
    A.T.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #21 9893408
    gaskoin
    Poziom 38  
    Nie ma.

    Po pierwsze nie kapuje po co Ci ten float. Nie musisz przeliczać danych z akcelerometru i żyroskopu na floaty, możesz wrzucać nieprzeliczone dane jako inty.

    Po drugie - Nastawy które Ci podałem są z innego układu (wirnik z zawieszeniem magnetycznym), więc na 99% dla Ciebie będą złe.

    Po trzecie - żeby cokolwiek regulować musisz podać jaka regulowana wartość ma być. W Twoim PIDzie skąd regulator ma "wiedzieć" jakie ma dać sterowanie skoro "nie wie" jaka jest wartość zadana ? W Twoim kodzie błąd jest stały (i bez sensu)
    więc sterowanie będzie ciągle narastało. Zobacz mój kod - ja tam steruje jedną wielkością i podaje dwa parametry.

    Chyba musisz doczytać o PIDzie, bez wiedzy jak to działa bez sensu jest to w ogóle implementować skoro nie rozumiesz tego wzoru.
  • #23 9894399
    A.T.
    Poziom 20  
    Dziękuję za odpowiedź.
    Floaty już zamieniłem na inty. Jeśli chodzi o wartości stałych to wiem, że muszą być dobrane indywidualnie. Dlatego na razie zostawiłem Twoje. Nie rozumiem tylko ostatniej uwagi. Dlaczego błąd jest stały. Przecież zmienna alpha to jest informacja z akcelerometru, nie jest to wartość stała. Wartość zadaną wziąłem pod uwage, ale ponieważ wydaje mi się że wynosi 0(zerowe odchylenie aby robot stał) to bez sensu jest ją odejmować.
    Dziękuję za pomoc.
    A.T.
  • REKLAMA
  • #24 9899093
    bolek
    Poziom 35  
    Nie ma znaczenia że masz 0 jako zadane, ważne ile masz aktualnie i ile masz mieć, czyli twoja odchyłka od zadanej.
    Jeśli np akt=5, zad=0, wzmocnienie KP=1 to na wyjściu masz -5. Jeśli KP=1.5 to dostajesz -7.5. A jeśli masz KP=3.47 to ile będzie na wyjściu?

    Teraz I.
    Dajmy na to że akt i zad j.w. Przy całkowaniu najczęściej zmienia się wzmocnenie i czas całkowania. Tak więc niech wzmocnienie będzie Ki=1, a czas=3s. Tak więc twoje wyjście będzie się zmieniać o 5 co każde 3 sekundy. Jeśli Ki=0.42 to co 3s zmieni się o 2.1

    Na temat D doszperaj sam i napisz jak rozumiesz. Patrz do innych kodów a nie nie dziwne wzory profesora na PID bo skubańce specjalnie tak je napisali żeby wydawało się abstrakcją.
    Ogólnie na wyjściu masz sume wszystkich członów (P+I+D), choć nie jest to regułą bo są np tylko P+I (zależy co kto ootrzebuje)
    Jak to ogarniesz to od razu zabierz się anty windup, po prostu przestajesz zwiększać całkę gdy osiągnie maksymalną wartość wyjścia i zmniejszać gdy osiągnie min.
    A jeszcze lepiej gdy każdy człon ograniczysz do skrajnych wartości jaki może osiągnąć twój element wykonawczy. Na deser procedura strojenia. Podpowiem ci też że skoro masz silniki to będziesz pracował na liczbach ze znakiem (np 0=stoi, + to w rawo, - to w lewo)
  • #25 9900116
    A.T.
    Poziom 20  
    Ja rozumiem D, że to jest iloczyn stałej Kd i różnicy (błąd - błąd poprzedni).
    Jednak dalej nie rozumiem gdzie jest błąd w tym co ja napisałem:/
    Nawet wgrałem to do procesora i chyba działa tak jak powinno. Gdy płytka z czujnikami jest w poziomie to wartość zmiennej output wynosi 126-128, gdy przechylę w którąś stronę to zmierza do 0 lub do 255, tak jak powinna.
    Bardzo proszę o pokazanie w której części kodu jest coś błędnego.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA