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

Program sterujący silnikami krokowymi w Delphi przez LPT/RS232 - jak zacząć?

Artas 15 Sie 2005 17:36 9236 17
  • #1 1736142
    Artas
    Poziom 19  
    Posty: 348
    Pomógł: 16
    Ocena: 8
    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! :)
  • #3 1736657
    Artas
    Poziom 19  
    Posty: 348
    Pomógł: 16
    Ocena: 8
    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. :)
  • Pomocny post
    #4 1736831
    marek_Łódź
    Poziom 36  
    Posty: 3103
    Pomógł: 208
    Ocena: 66
    Robiłem kiedyś coś takiego w Turbo Pascalu. W Delphi to będzie jakoś tak (założenie silnik unipolarny, czterofazowy):

    
    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.
  • #5 1736925
    Artas
    Poziom 19  
    Posty: 348
    Pomógł: 16
    Ocena: 8
    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. :)
  • #6 1736953
    konradek26
    Poziom 17  
    Posty: 274
    Pomógł: 19
    Ocena: 6
    ja ci mogę dać plik .bat odblokowujący porty, jeżeli chcesz -> gg
  • #7 1736991
    marek_Łódź
    Poziom 36  
    Posty: 3103
    Pomógł: 208
    Ocena: 66
    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.
  • #9 1741400
    sivex
    Poziom 27  
    Posty: 815
    Pomógł: 113
    Ocena: 25
    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
  • Pomocny post
    #10 1746228
    marek_Łódź
    Poziom 36  
    Posty: 3103
    Pomógł: 208
    Ocena: 66
    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
  • Pomocny post
    #11 1753964
    grigor1
    Poziom 15  
    Posty: 120
    Pomógł: 9
    Ocena: 3
    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
  • #12 1754059
    marek_Łódź
    Poziom 36  
    Posty: 3103
    Pomógł: 208
    Ocena: 66
    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.
  • #13 1755123
    Artas
    Poziom 19  
    Posty: 348
    Pomógł: 16
    Ocena: 8
    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ń.
  • #14 1755620
    marek_Łódź
    Poziom 36  
    Posty: 3103
    Pomógł: 208
    Ocena: 66
    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.
  • Pomocny post
    #15 1758168
    snakemen
    Poziom 12  
    Posty: 55
    Pomógł: 3
    Ocena: 7
    Poniżej kod programu napisanego w Builder C++ a w zalączniku dodany skompilowany exe'c



    
    //---------------------------------------------------------------------------
    
    #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();        
    }
    //---------------------------------------------------------------------------
    
    Załączniki:
    • Silnik.rar (1.04 MB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #16 1759450
    Artas
    Poziom 19  
    Posty: 348
    Pomógł: 16
    Ocena: 8
    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. :(
  • Pomocny post
    #17 1759724
    snakemen
    Poziom 12  
    Posty: 55
    Pomógł: 3
    Ocena: 7
    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
  • #18 1981005
    Artas
    Poziom 19  
    Posty: 348
    Pomógł: 16
    Ocena: 8
    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?

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy tworzenia programu w Delphi (Object Pascal) do sterowania silnikami krokowymi przez port LPT lub RS232 w systemie Windows XP. Główne funkcje programu to sterowanie ruchem silnika krokowego do przodu i do tyłu o określoną liczbę kroków, zatrzymanie po zadanej liczbie kroków oraz obsługa trybów pełnokrokowego i półkrokowego. Uczestnicy podają przykładowy kod w Delphi i C++ do generowania impulsów sterujących, wskazują na konieczność odblokowania portów LPT w Windows XP (np. za pomocą plików .bat lub bibliotek DLL) oraz zalecają stosowanie sterowników scalonych L297 i L298 do bezpiecznego i efektywnego sterowania prądowego silników. Poruszono kwestie techniczne dotyczące budowy układu sterowania, w tym konieczność zastosowania półmostków do sterowania fazami silnika bipolarnym oraz podtrzymywania prądu na postoju, aby zapobiec opadaniu obciążenia na prowadnicy pionowej. Wskazano na różnice w silnikach unipolarnych z różną liczbą przewodów (4 lub 5) i potrzebę ich identyfikacji. Podkreślono, że program powinien realizować określoną liczbę kroków przez odpowiednią liczbę pętli sterujących. Wskazano również na dostępne materiały i schematy na forach takich jak elektroda.pl oraz cnc.info.pl. Problemy z odblokowaniem portów w Windows XP SP2 zostały zauważone, co może wymagać dodatkowych działań.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA