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.

Jak napisać program sterujący silniki krokowe?

Artas 15 Sie 2005 17:36 7931 17
  • #1 15 Sie 2005 17:36
    Artas
    Poziom 19  

    Witam wszystkich!

    Mam taki problem. Chciałbym zacząć pisać program dla Windows który sterowałby silnikami krokowymi. Język programowania najlepiej Delhi (Object Pascal). Port najlepiej LPT, ale może być też RS232. Program musiałby wykonywać następujące funkcje:

    - Sterowanie silnikiem do przodu określoną ilość kroków.
    - Sterowanie silnikiem do tyłu określoną ilość kroków.
    - Zatrzymanie silnika po określonej liczbie kroków.
    - Dwa tryby pracy pełnokrokowe i półkrokowe.

    I tu prośba do was. Może ktoś ma taki program, źródła w Delhi. Chciałbym zobaczyć jak realizuje się takie sterowanie. Szukałem kilka godzin w internecie i kilka stron znalazłem, ale były tylko niektóre procedury opisane i to jeszcze nie w tym języku, co bym chciał. Liczę, że ktoś pomorze. Jeśli macie jakieś ciekawe strony z tym związane, kursy itp. To prosiłbym o zamieszczenie. Z góry dziękuję i pozdrawiam! :)

    0 17
  • #3 15 Sie 2005 20:46
    Artas
    Poziom 19  

    Dzięki za pomoc, ale to gotowy program. Mnie bardzo by pomógł jakiś kurs krok po kroku z kodem źródłowym takiego programu. Najlepiej w Delphi. :)

    0
  • Pomocny post
    #4 15 Sie 2005 21:45
    marek_Łódź
    Poziom 36  

    Robiłem kiedyś coś takiego w Turbo Pascalu. W Delphi to będzie jakoś tak (założenie silnik unipolarny, czterofazowy):

    Code:

    unit Motor;

    interface

    procedure MotorFwdStep;   //Krok w przód
    procedure MotorBckStep;   //Krok w tył
    procedure GoNSteps(n : SmallInt); //Ruch w przód i wstecz
    procedure Start_Stop_Motor(v0,v1,n : SmallInt); //Zmiana prędkosci

    implementation

    Type MotorCtrlArray = array[0..8] of byte;

    Const StepMode     : MotorCtrlArray = (4,$01,$02,$04,$08,$00,$00,$00,$00);
          HalfStepMode : MotorCtrlArray = (8,$01,$03,$02,$06,$04,$0C,$08,$09);

          HalfStep   : boolean = false;
          Index      : ShortInt = 0;
          MotorDelay : SmallInt = 10;     /Step time 10ms

    var DataPort, StatPort, CtrlPort  : SmallInt;
        dd : byte;
        CurrentMode : MotorCtrlArray;

    procedure Delay(n : smallInt); begin end;

    procedure MotorControl;

    begin
    dd:=CurrentMode[Index];
    asm
      mov dx,DataPort
      mov al,dd
      out dx,al
    end
    end;

    procedure CXInit;

    begin
    DataPort:=$378;       //LPT1
    StatPort:=DataPort+1;
    CtrlPort:=DataPort+2;
    if HalfStep then
      CurrentMode:=HalfStepMode
    else
      CurrentMode:=StepMode;
    MotorControl;
    end;

    procedure MotorFwdStep;   //Krok w przód

    begin
    Inc(Index);
    if Index>CurrentMode[0] then
      Index:=1;
    MotorControl;
    end;

    procedure MotorBckStep;   //Krok w tył

    begin
    Dec(Index);
    if Index<=0 then
      Index:=CurrentMode[0];
    MotorControl;
    end;

    procedure GoNSteps(n : SmallInt);  //Ruch w przód i wstecz

    var i : integer;

    begin
    if n>0 then
      for i:=1 to n do
        begin
        MotorFwdStep;
        Delay(MotorDelay);
        end
    else
      for i:=-1 downto n do
        begin
        MotorFwdStep;
        Delay(MotorDelay);
        end
    end;

    procedure Start_Stop_Motor(v0,v1,n : SmallInt); //Zmiana prędkosci

    var dld : single;
        i   : SmallInt;
    begin
    MotorDelay:=v0;
    dld:=(v1-v0)/n;
    for i:=1 to n do
      begin
      if dld>0 then
        MotorFwdStep
      else
        MotorBckStep;
      Delay(MotorDelay);
      MotorDelay:=Round(v0+i*dld)
      end;
    MotorDelay:=v1;
    end;

    end.



    Prędkość ruchu regulujemy przez zmianę opóźnienia MotorDelay. W całym zestawie brakuje tylko funkcji Delay (opóźnienie w ms, można wyznaczyć z czasu systemowego np funkcja Now).

    Przy starcie i hamowaniu (przy rozpędzaniu do większych prędkości) należy stopniowo zmieniać prędkość. Próba startu z dużą prędkością może spowodować zgubienie kroków, a wyżej poślizg bez uruchomienia silnika. Podobnie przy zatrzymywaniu należy zwalniać stopniowo, bo nastąpi rozjechanie pozycji z ilością kroków sterowania.

    Parametry rozruchu i hamowania zależą od momentu (bezwładności i obciążenia) na osi silnika oraz momentu silnika. Impulsy nie mogą wyprzedzać możliwości mechanicznych układu silnik-obiekt.

    Całość pisana przed chwilą na kolanie, ale nie powinno być większych błędów. Sterowanie przez cztery młodsze bity portu LPT. Przy zmianie liczby faz lub dla silników sterowanych bipolarnie można wykorzystać starsze bity portu zmieniając jednocześnie tablice sterujące (algorytmy pozostają bez zmian).

    Przeanalizuj to, co się dzieje na porcie (fazach silnika), jeśli jeszcze coś będzie niejasne - pytaj.

    0
  • #5 15 Sie 2005 22:13
    Artas
    Poziom 19  

    Wielkie dzięki, to już mi cokolwiek mówi. Jeśli ktoś ma jeszcze jakieś kody to bardzo proszę zamieścić. Będę bardzo wdzięczny. Jeszcze jedno. Dobrze by było gdyby program sam odblokował dostęp do portu LPT pod Windows XP. :)

    0
  • #6 15 Sie 2005 22:23
    konradek26
    Poziom 17  

    ja ci mogę dać plik .bat odblokowujący porty, jeżeli chcesz -> gg

    0
  • #7 15 Sie 2005 22:37
    marek_Łódź
    Poziom 36  

    Artas napisał:
    Dobrze by było gdyby program sam odblokował dostęp do portu LPT pod Windows XP. :)


    Jeśli chcesz to zrobić elegancko i wmontować w program, najlepiej ściągnąć jakąś bibliotekę (np. .DLL). Po pobieżnym przeszukaniu tematu znalazłem coś takiego,

    http://www.lvr.com/parport.htm

    ale już mi się nie chce dziś w tym grzebać. Jak masz ochotę poszukaj tam, powinieneś coś znaleźć. Ewentualnie po delphi faq'ach w sieci.

    0
  • #9 17 Sie 2005 14:58
    sivex
    Poziom 27  

    Wydaje mi sie ze przed napisaniem programu powinienes wiedziec jaki masz silnik, jaka jest jego zasada dzialania... i co dalej za tym idzie jakie stany powinny pojawic sie na porcie lpt jezeli chcesz go do tego wykorzystac.
    Tu masz wszystkie materialy ktore powinny byc ci do tego potrzebne:

    http://www.r2d2.faith.pl/opis_podzespolow.html#silnik_opis
    https://www.elektroda.pl/rtvforum/topic328008.html

    pozdrawiam

    0
  • Pomocny post
    #10 19 Sie 2005 08:10
    marek_Łódź
    Poziom 36  

    sivex napisał:
    Wydaje mi się ze przed napisaniem programu powinienes wiedziec jaki masz silnik, jaka jest jego zasada dzialania... i co dalej za tym idzie jakie stany powinny pojawic się na porcie lpt jezeli chcesz go do tego wykorzystac.


    Generalna zasada jest taka, że musisz wygenerować napięcie wielofazowe podając kolejne impulsy na poszczególne fazy i zapewniając odpowiedni kierunek "rotacji" tych napięć. W układzie połączeń silnika sterowanego bipolarnie nie wystarczą tranzystory OC. W każdej fazie trzeba dać układ przeciwsobny (zwany inaczej półmostkiem) tak, żeby można było ją wysterować z obu biegunów zasilania. W układzie sterowania dobrze jest zapewnić forsowanie napięcia przy podaniu impulsu na silnik i potem jego obniżenie. Ze względu na sporą indukcyjność zastępczą faz (ich własna indukcyjność+to, co się indukuje z powodu ruchu) taki sposób sterowania zapewni odpowiednią dynamikę. W najprostszym układzie wystarczy dać niewielkie rezystory w każdej fazie (dobrane do rezystancji uzwojeń silnika.
    I jeszcze problem postoju. Dobrze jest podtrzymywać zasilanie faz (chociażby niewielkim prądem) na postoju, gdyż zwiększa to moment trzymający).

    Na porcie LPT dobrze jest zastosować optoizolację, bo w takim eksperymentalnym układzie silnoprądowym nie trudno o zwarcie czy przepięcia i wtedy można uwalić komputer, a szkoda ;-).

    ps w moich procedurkach był błąd indeksacji...poprawiłem

    Powodzenia

    0
  • Pomocny post
    #11 22 Sie 2005 09:36
    grigor1
    Poziom 15  

    Witam,
    do ruszenia krokowców z poziomu LPT najlepiej nadaje sie sterownik oparty o układ L297 i L298 poszukaj sobie schematu lub gotowego układu na elektrodzie lub na www.cnc.info.pl tam są fachowcy od strony elektronicznej. Program do uruchomienia takiej płytki ma zadanie wyprowadzić na LPT dwa sygnały STEP i DIR. DIR realizuje kierunek obrotu np. 0 w lewo, 1 w prawo, a STEP to ilość kroków jaką ma wykonać silnik np. 10 impulsów = 10 kroków. Cały problem od strony 'prądowej' jest realizowany przez sterownik więc nie masz możliwości uszkodzenia kompa. Wykonanie takiego sterownika to nie problem nawet gdy kupisz gotową płytkę to cena będzie bardzo niska a w wiekszości tych ukladów jest już funkcja sterowania pełnym krokiem lub półkrokiem realizowana sprzętowo.
    Pozdrawiam

    0
  • #12 22 Sie 2005 10:15
    marek_Łódź
    Poziom 36  

    Zastosowanie scalonego sterownika upraszcza układ i program nie absorbuje komputera. Można też dołożyć jakiś mały odpowiednio oprogramowany procesor i kawałek drivera prądowego.

    0
  • #13 22 Sie 2005 17:31
    Artas
    Poziom 19  

    Dzięki za wasze rady. :) Niektóre naprawdę pomogły. Mam jeszcze pytanko. Mam prowadnice ustawioną pionowo do góry. Jak zrobić by przedmiot poruszający się po tej prowadnicy przebył odpowiednią ilość kroków poczym zatrzymałby się w miejscu i nie opadał w dół? Schematy już jako takie znalazłem. Najprostszy to jeden scalak ULN2803. Tylko jest jeden problem, bo mam jeden silnik z pięcioma przewodami a drugi z czterema. A na schemacie mam tylko połączenie dwóch silników o takiej samej liczbie wyprowadzeń.

    0
  • #14 22 Sie 2005 20:27
    marek_Łódź
    Poziom 36  

    Artas napisał:
    mam jeden silnik z pięcioma przewodami a drugi z czterema. A na schemacie mam tylko połączenie dwóch silników o takiej samej liczbie wyprowadzeń.


    Masz problem, powinieneś najpierw określić co to za silnik, a potem realizować układ sterowania. Przy pięciu przewodach to jest pewnie silnik unipolarny (przy czterech pewnie też). Można to sprawdzić omomierzem (jedna faza silnika - R, dwie fazy 2R).

    Aby silnik trzymał trzeba podtrzymać prąd (niekonieczniew na poziomie maksymalnym). Prąd podtrzymania mozna zmniejszyć zmniejszając współczynnik wypełnienia.

    0
  • Pomocny post
    #15 23 Sie 2005 19:01
    snakemen
    Poziom 11  

    Poniżej kod programu napisanego w Builder C++ a w zalączniku dodany skompilowany exe'c



    Code:

    //---------------------------------------------------------------------------

    #include <vcl.h>
    #pragma hdrstop

    #include "silnik_u.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    Boolean prawo,lewo;
    byte typ;
    unsigned short adres;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }

    //---------------------------------------------------------------------------
    void port(byte dane)
    {
     asm
     {
      mov   dx,adres
      mov   al,dane
      out   dx,al
     }
    }
    void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
    {
     Form1->Timer1->Enabled=prawo;
     Form1->Timer4->Enabled=lewo;
     Form1->StatusBar1->SimpleText="Silnik uruchomiony";
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
     if ((Form1->RadioGroup2->ItemIndex==0) ||(Form1->RadioGroup2->ItemIndex==2)) port(1);
      else  if (Form1->RadioGroup2->ItemIndex==1) port(9);
     Form1->Timer1->Enabled=False;
     Form1->Timer2->Enabled=prawo;
     if (Form1->RadioGroup2->ItemIndex==2) Form1->Timer8->Enabled=lewo;
      else  Form1->Timer4->Enabled=lewo;

    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer2Timer(TObject *Sender)
    {
     if (Form1->RadioGroup2->ItemIndex==0) port(2);
      else  if ((Form1->RadioGroup2->ItemIndex==1) ||(Form1->RadioGroup2->ItemIndex==2)) port(3);
     Form1->Timer2->Enabled=False;
     Form1->Timer3->Enabled=prawo;
     Form1->Timer1->Enabled=lewo;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer3Timer(TObject *Sender)
    {
     if (Form1->RadioGroup2->ItemIndex==0) port(4);
      else  if (Form1->RadioGroup2->ItemIndex==1) port(6);
       else  if (Form1->RadioGroup2->ItemIndex==2) port(2);




     Form1->Timer3->Enabled=False;
     Form1->Timer4->Enabled=prawo;
     Form1->Timer2->Enabled=lewo;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer4Timer(TObject *Sender)
    {
     if (Form1->RadioGroup2->ItemIndex==0) port(8);
      else  if (Form1->RadioGroup2->ItemIndex==1) port(12);
       else  if (Form1->RadioGroup2->ItemIndex==2) port(6);
     Form1->Timer4->Enabled=False;

     if (Form1->RadioGroup2->ItemIndex==2)
     {
      Form1->Timer5->Enabled=prawo;
      Form1->Timer3->Enabled=lewo;
     }
      else
      {
       Form1->Timer1->Enabled=prawo;
       Form1->Timer3->Enabled=lewo;
      }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
    {
     Form1->Timer1->Enabled=False;
     Form1->Timer2->Enabled=False;
     Form1->Timer3->Enabled=False;
     Form1->Timer4->Enabled=False;
     Form1->Timer5->Enabled=False;
     Form1->Timer6->Enabled=False;
     Form1->Timer7->Enabled=False;
     Form1->Timer8->Enabled=False;
     port(0);
     Form1->StatusBar1->SimpleText="Silnik zatrzymany";
    }
    //---------------------------------------------------------------------------

    void __fastcall TForm1::TrackBar1Change(TObject *Sender)
    {
     Form1->Timer1->Interval=(Form1->TrackBar1->Position*10);
     Form1->Timer2->Interval=(Form1->TrackBar1->Position*10);
     Form1->Timer3->Interval=(Form1->TrackBar1->Position*10);
     Form1->Timer4->Interval=(Form1->TrackBar1->Position*10);
     Form1->Timer5->Interval=(Form1->TrackBar1->Position*10);
     Form1->Timer6->Interval=(Form1->TrackBar1->Position*10);
     Form1->Timer7->Interval=(Form1->TrackBar1->Position*10);
     Form1->Timer8->Interval=(Form1->TrackBar1->Position*10);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
     Form1->RadioGroup1Click(Sender);
     Form1->TrackBar1Change(Sender);
     Form1->ComboBox1Change(Sender);
    }
    //---------------------------------------------------------------------------

    void __fastcall TForm1::RadioGroup1Click(TObject *Sender)
    {
     if (Form1->RadioGroup1->ItemIndex==0)
      {
       prawo=1;
       lewo=0;
      }
      else
      {
       prawo=0;
       lewo=1;
      }
    }
    //---------------------------------------------------------------------------

    void __fastcall TForm1::ComboBox1Change(TObject *Sender)
    {
     if (Form1->ComboBox1->ItemIndex==0) adres=888;
      else if (Form1->ComboBox1->ItemIndex==0) adres=632;
       else adres=956;
    }
    //---------------------------------------------------------------------------

    // if (Form1->RadioGroup2->ItemIndex==0) port(1);
    //  else port(9);
    void __fastcall TForm1::Timer5Timer(TObject *Sender)
    {
     port(4);
     Form1->Timer5->Enabled=False;
     Form1->Timer6->Enabled=prawo;
     Form1->Timer4->Enabled=lewo;
    }
    //---------------------------------------------------------------------------

    void __fastcall TForm1::Timer6Timer(TObject *Sender)
    {
     port(12);
     Form1->Timer6->Enabled=False;
     Form1->Timer7->Enabled=prawo;
     Form1->Timer5->Enabled=lewo;
    }
    //---------------------------------------------------------------------------

    void __fastcall TForm1::Timer7Timer(TObject *Sender)
    {
     port(8);
     Form1->Timer7->Enabled=False;
     Form1->Timer8->Enabled=prawo;
     Form1->Timer6->Enabled=lewo;
    }
    //---------------------------------------------------------------------------

    void __fastcall TForm1::Timer8Timer(TObject *Sender)
    {
     port(9);
     Form1->Timer8->Enabled=False;
     Form1->Timer1->Enabled=prawo;
     Form1->Timer7->Enabled=lewo;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
    {
     Form1->Timer1->Enabled=False;
     Form1->Timer2->Enabled=False;
     Form1->Timer3->Enabled=False;
     Form1->Timer4->Enabled=False;
     Form1->Timer5->Enabled=False;
     Form1->Timer6->Enabled=False;
     Form1->Timer7->Enabled=False;
     Form1->Timer8->Enabled=False;
     port(0);
     Form1->Close();       
    }
    //---------------------------------------------------------------------------

    0
    Załączniki:
  • #16 24 Sie 2005 02:39
    Artas
    Poziom 19  

    O takie coś mi chodziło. Tylko jeszcze, aby ustalić liczbę kroków, jaką silnik ma przebyć i po jakiej ma się zatrzymać. Kroki można wybierać w przód i w tył. No i jeszcze takie coś do zaprogramowania kroków przez użytkownika. Ale no przy tym powinienem sobie sam poradzić. Chociaż jeśli ktoś lubi wyzwania. Program po uruchomieniu działa, ale jak włączę start to wywala masę błędów i za chwile okienek jest tyle, że komputer się zacina. Otwierałem porty i powinno być wszystko dobrze. Mam Windowsa XP Profesjonalnego. :(

    0
  • Pomocny post
    #17 24 Sie 2005 09:27
    snakemen
    Poziom 11  

    Po odblokowaniu portu wszystko powinno chodzic poprawnie

    A co do wykonania okreslonej liczby krokow przez silnik to moge podpowiedziec ze nalezy wykonac jedynie okreslona (zalezna od liczy krokow) liczbe petli sterujacych silnikiem

    Pozdrawiam

    0
  • #18 13 Lis 2005 02:17
    Artas
    Poziom 19  

    Hmmm muszę bardziej nad tym posiedzieć narazie rezultaty są ok. :) Dostałem maila od elektrody by wypowiedzieć sie lub zamknąc temat jesli naprawdę trzeba to temat można zamknąć. Już chyba dojdę sam do reszty. Jesli jednak nie śpieszy sie to prosiłbym o pozostawienie tematu otwartego. Mam mało czasu dlatego narazie nie poświecam temu tematowi zbyt wiele czasu. Co nie znaczy, że tak będzie zawsze. :)

    Co do odblokowywania portów to nie wiem czemu ale czasem program nie odblokowuje portów. :( Czasam zaskoczy a czasem nie. I jeszcze jedno. Jeśli mam zainstalowany SP2 To czy coś zmienia sie z portami?

    0