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

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

A.T. 31 Sie 2011 10:29 2124 24
  • #1 31 Sie 2011 10:29
    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.

    0 24
  • #2 31 Sie 2011 10:49
    tmf
    Moderator Mikrokontrolery Projektowanie

    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ą?

    0
  • #3 31 Sie 2011 11:04
    gaskoin
    Poziom 38  

    Pokaż no ten twój PID, bo z reguły tak jak pisze tmf niepotrzebny Ci jest float.

    0
  • #4 31 Sie 2011 11:13
    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.

    Code:
    #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.

    0
  • #5 31 Sie 2011 11:49
    gaskoin
    Poziom 38  

    Ło matko skąd to masz :D

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

    Kod: 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 :)

    0
  • #6 02 Wrz 2011 11:52
    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.

    0
  • #7 02 Wrz 2011 12:14
    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...

    0
  • #8 02 Wrz 2011 12:32
    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ć.

    0
  • #9 02 Wrz 2011 12:36
    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:/

    0
  • #10 02 Wrz 2011 12:51
    gaskoin
    Poziom 38  

    Wartość aktualną i zadaną.

    0
  • #11 02 Wrz 2011 13:39
    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.

    0
  • #12 02 Wrz 2011 13:45
    LordBlick
    VIP Zasłużony dla elektroda

    Każdą oś odchylenia przetwarzaj w oddzielnych regulatorach PID

    0
  • #13 02 Wrz 2011 14:17
    A.T.
    Poziom 20  

    Jak każdą? Przecież odchylenie jest tylko w jednej osi.

    0
  • #14 02 Wrz 2011 22:25
    LordBlick
    VIP Zasłużony dla elektroda

    Nie podałeś w sumie żadnego rysunku i myślałem, że jest to bardziej zaawansowana wersja... :)

    Link

    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...

    0
  • #15 03 Wrz 2011 10:07
    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.

    0
  • #16 03 Wrz 2011 10:25
    dondu
    Moderator Mikrokontrolery Projektowanie

    A.T. napisał:
    Proszę o pomoc. Sam sobie niestety nie potrafię poradzić, ponieważ tak sobie rozumiem zasadę działania regulatora PID:/

    Jak u Ciebie z angielskim?: http://letsmakerobots.com/node/865

    0
  • #17 03 Wrz 2011 11:55
    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.

    0
  • #18 03 Wrz 2011 13:43
    LordBlick
    VIP Zasłużony dla elektroda

    Na razie uśredniaj i podawaj to samo na oba silniki jednocześnie...

    0
  • #19 03 Wrz 2011 16:23
    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 ! :)

    0
  • #20 04 Wrz 2011 00:46
    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
    Zaloguj się, aby zobaczyć kod

    0
  • #21 04 Wrz 2011 10:35
    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.

    0
  • #23 04 Wrz 2011 15:47
    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.

    0
  • #24 05 Wrz 2011 22:21
    bolek
    Specjalista - oświetlenie sceniczne

    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)

    0
  • #25 06 Wrz 2011 11:28
    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
    Zaloguj się, aby zobaczyć kod

    0