Schrittmotorsteuerung ?!

Hardware- und Elektronikbasteleien, Ansteuerung von Schnittstellen und Peripherie.
Fragen zu "Consumer"-Problemen kommen in Offtopic.
Benutzeravatar
Then
Beiträge: 247
Registriert: 06.09.2004 13:26
Wohnort: Siegen

Schrittmotorsteuerung ?!

Beitrag von Then »

Hallo !

Habe mit der "INPOUT32.DLL" rumgefummelt und meine 3 Schrittmotoren auch zum Laufen bekommen, aber es ist doch noch recht langsam !

Vorallem verstehe ich folgendes nicht (Habe den Code nicht hier, aber...) :


Code: Alles auswählen

...
FOR t=1 to 100 ; 100 Schritte soll er machen
 CallFunction(0,"Out32",$888,%01000000) ; X-Achse fährt einen Schritt
 CallFunction(0,"Out32",$888,%00000000) ; Nullbit schicken - Keine Ahnung warum, aber ohne funzt es nicht !
 Delay(1) ; Auch das kann ich nicht weglassen - summt sonst nur !
Next
...
Das ganze läuft ja, ich steuere damit eine CNC-Fräse und alle Motoren tun was sie sollen, aber im DOS gehts n Tick schneller ! Gibts da ne schnellere LIB oder so, mit der ich das auch hinkriege ?? /:->
the one and only
Beiträge: 696
Registriert: 26.09.2004 20:17
Kontaktdaten:

Beitrag von the one and only »

Auf irgendner Visual Basic Seite gabs mal ein Tutorial zum ansteuern von Schrittmotoren (vb-fun.de wars glaub ich). Da wir alle wissen dass Visual Basic böse ist möchte ich meine Augen nicht verbrennen und diese Seite besuchen, aber ich denke dass es kein großes Problem sein sollte die Codebeispiele aus dem VB Tutorial auf Purebasic umzuschreiben. :mrgreen:
ORANGE
Beiträge: 19
Registriert: 29.12.2004 21:03

Beitrag von ORANGE »

Das Problem ist das du die Schrittmotoren falsch ansteuerst. Die Teile haben eine An- und Abfallszeit. Mach einfach nen kleinen delay nach dem verschieben des Bits. Wie groß der delay sein muß hängt von der maximal Frequenz(U/min) deines Schrittmotors ab. Damit kannst du dir das Null setzen sparen. Das Null setzen darfst du nur beim anhalten nicht vergessen, sonst raucht der Motor ab.
Benutzeravatar
Then
Beiträge: 247
Registriert: 06.09.2004 13:26
Wohnort: Siegen

Beitrag von Then »

Hm... verstehe nicht so ganz was Du meinst ! Kannste es mir in Code etwas verdeutlichen ?!

:freak:
ORANGE
Beiträge: 19
Registriert: 29.12.2004 21:03

Beitrag von ORANGE »

Vergiss was ich sagte. Der 1ms delay ist zu groß. Bei 1ms ist f=1/0,001 gleich 1000Hz. Wenn der Motor pro Schritt 90° dreht wären das 1000/4=250U/min. Das ist wirklich etwas langsam. Also einfach selber ne Zeitschleife basteln.

Motor mit 4 Schritten pro Umdrehung und D4 - D7 als Steuerleitung:

Code: Alles auswählen

... 
FOR t=1 to 100 ; 100 Umdrehungen
 CallFunction(0,"Out32",$888,%10000000) ; 
 CallFunction(0,"Out32",$888,%00000000) ; 
 Gosub schleife;
 CallFunction(0,"Out32",$888,%01000000) ; 
 CallFunction(0,"Out32",$888,%00000000) ; 
 Gosub schleife;
 CallFunction(0,"Out32",$888,%00100000) ; 
 CallFunction(0,"Out32",$888,%00000000) ; 
 Gosub schleife;
 CallFunction(0,"Out32",$888,%00010000) ; 
 CallFunction(0,"Out32",$888,%00000000) ; 
 Gosub schleife;
Next 
... 

schleife:
x = 0
Repeat
x = x + 1
Until x = ; ???
Return
Das Problem ist halt das die Schleife von der Cpu Geschwindigkeit abhängt. Vielleicht hat jemand ne Idee wie man nen festen Delay kleiner 1ms erzeugt.
Benutzeravatar
Then
Beiträge: 247
Registriert: 06.09.2004 13:26
Wohnort: Siegen

Beitrag von Then »

Genau das ist das eigentliche Problem ! Die Steuerung für die Achsen inkl. Richtungen habe ich nun realisiert, aber es hängt in der Tat am DELAY() ! gab es da nicht mal was kleiners ?! :?:
Benutzeravatar
Falko
Admin
Beiträge: 3531
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.0
Kontaktdaten:

Beitrag von Falko »

vielleicht hilft diese Delay-schleife weiter.

Code: Alles auswählen

Procedure Delayus(t.l) ; Rechnerabhängig!
  Structure DLong 
    lowlong.l 
    hilong.l 
  EndStructure 
  DLong=0 
  hitimefreq.DLong 
  QueryPerformanceFrequency_(@hitimefreq) 
  hitimecount1.DLong 
  hitimecount2.DLong 
  QueryPerformanceCounter_(@hitimecount1) 
  Repeat 
    QueryPerformanceCounter_(@hitimecount2) 
  Until Int((hitimecount2\lowlong - hitimecount1\lowlong)/(hitimefreq\lowlong/1000000.0))>=t 
;Debug "time in µ: " + Str((hitimecount2\lowlong - hitimecount1\lowlong)/(hitimefreq\lowlong/1000000.0)) 
EndProcedure 
Bild
Win10 Pro 64-Bit, PB_5.4,GFA-WinDOS, Powerbasic9.05-Windows, NSBasic/CE, NSBasic/Desktop, NSBasic4APP, EmergenceBasic
Benutzeravatar
Then
Beiträge: 247
Registriert: 06.09.2004 13:26
Wohnort: Siegen

Beitrag von Then »

@Falko : Sieht gut aus - Pause ist deutlich kleiner. Ich sollte so um die 0.3ms Pause haben. Werde ich heute Abend mal testen !! :allright: Danke
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Beitrag von NicTheQuick »

Ich habe hier auch zwei Schrittmotoren, die ich mit PureBasic ansteuere. Die haben vier Anschlüsse, wovon zwei davon jeweils negiert zu den anderen zwei sind. Da ich aber noch keine NOT-Gatter hier habe, brauche ich 4 Bits pro Motor, d.h. ich kann am LPT nur zwei Schrittmotoren ansteuern, was aber tadellos funktioniert. Die Motoren machen 100 Schritte pro Umdrehung, also 3.6° pro Schritt, was bei minimal 2 ms Umschaltzeit funktioniert. Wenn ich auf 1 ms pro Schritt gehe, fehlen einige Schritte und das ganze läuft nicht rund. Schade eigentlich.

Hier ist mein Code dafür, falls ihn jemand braucht:

Code: Alles auswählen

#InpOut_ID = 1

Global InpOut32Aktiv.l
Procedure OpenInpOut32()
  Protected Result.l
  Result = OpenLibrary(#InpOut_ID, "InpOut32.dll")
  If Result = #False
    InpOut32Aktiv = #False
    MessageRequester("ERROR", "InpOut32.dll wurde nicht gefunden oder ist korrupt.", #MB_ICONERROR)
    End
  Else
    InpOut32Aktiv = #True
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure CloseInpOut32()
  CloseLibrary(#InpOut_ID)
  InpOut32Aktiv = #False
EndProcedure

Procedure SetBits(Value.l)
  Protected Address.l
  Address = $378
  ProcedureReturn CallFunction(#InpOut_ID, "Out32", Address, Value)
EndProcedure

Procedure.l GetBits()
  Protected Address.l, Value.l
  Address = $379
  Value = CallFunction(#InpOut_ID, "Inp32", Address)
  ProcedureReturn Value
EndProcedure

Procedure.l Inp32(Address.l)
  Protected Value.l
  Value = CallFunction(#InpOut_ID, "Inp32", Address)
  ProcedureReturn Value
EndProcedure

Procedure Out32(Address.l, Value.l)
  ProcedureReturn CallFunction(#InpOut_ID, "Out32", Address, Value)
EndProcedure

Procedure CheckInpOut32Functions()
  Protected FunctionName.s
  If InpOut32Aktiv
    Restore CheckInpOut32FunctionsData
    For a.l = 1 To 2
      Read FunctionName
      If IsFunction(#InpOut_ID, FunctionName) = #False
        MessageRequester("ERROR", "Die Funktion " + Chr(34) + FunctionName + Chr(34) +" wurde nicht gefunden", #MB_ICONERROR)
        ProcedureReturn #False
      EndIf
    Next
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
  DataSection
    CheckInpOut32FunctionsData:
    Data.s "Inp32", "Out32"
  EndDataSection
EndProcedure

Dim Motor.b(3)
Motor(0) = %1001
Motor(1) = %1100
Motor(2) = %0110
Motor(3) = %0011
MaxMotorSchritt.l = 4   ; Bits pro Motor

MaxPos.l = 400          ; Schritte für das Trackbargadget

Pos1.l = 0              ; Startposition von Motor 1
NewPos1.l = 0
Pos2.l = 0              ; Startposition von Motor 2
NewPos2.l = 0

t_delta.l = 2           ; Umschaltzeit pro Schritt
t_old.l = ElapsedMilliseconds()

If OpenInpOut32()
  Win_Main.l = OpenWindow(#PB_Any, 0, 0, 402, 40, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "Schrittmotor")
  If Win_Main
    If CreateGadgetList(WindowID(Win_Main))
      Gad_Track1.l = TrackBarGadget(#PB_Any, 1,  1, 400, 18, 0, MaxPos)
      Gad_Track2.l = TrackBarGadget(#PB_Any, 1, 21, 400, 18, 0, MaxPos)
      
      Repeat
        EventID.l = WindowEvent()
        Select EventID
          Case #PB_Event_CloseWindow
            Break
          
          Case #PB_EventGadget
            Select EventGadgetID()
              Case Gad_Track1
                NewPos1 = GetGadgetState(Gad_Track1)
              Case Gad_Track2
                NewPos2 = GetGadgetState(Gad_Track2)
            EndSelect
            
          Case 0
            Delay(1)
        EndSelect
        
        If t_old + t_delta < ElapsedMilliseconds()
          If Pos1 > NewPos1 : Pos1 - 1 : ElseIf Pos1 < NewPos1 : Pos1 + 1 : EndIf
          If Pos2 > NewPos2 : Pos2 - 1 : ElseIf Pos2 < NewPos2 : Pos2 + 1 : EndIf
          
          SetBits(Motor(Pos1 % MaxMotorSchritt) + Motor(Pos2 % MaxMotorSchritt) << MaxMotorSchritt)
          
          t_old = ElapsedMilliseconds()
        EndIf
      ForEver
    EndIf
    CloseWindow(Win_Main)
  EndIf
  SetBits(0)
  CloseInpOut32()
EndIf
Bild
Benutzeravatar
Falko
Admin
Beiträge: 3531
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.0
Kontaktdaten:

Beitrag von Falko »

Über 2 ULN-2803-IC's kann man bei einer 4-Bit-Ansteuerung
lt. dem Buch von Burkhard Kainka u. Hans-Joachim Berndt
"PC-Schnittstellen unter Windows"

"3 Motoren" ansteuern und über Error,Select und PE 3 Endschalter abfragen.
Das Programm (Delphi) dazu habe ich auch im Buch, aber mangels der IC's noch nicht in PB probiert. Werd's aber bald machen :mrgreen:

Die zusätzlichen 4 Leitungen, damit man den auch einen 3. Motor ansteuern
kann, sind dann nicht nur die 8 Datenleitungen für nur 2 Motoren, sondern die weiteren 4-Leitungen: Strobe, AutoFeed, Init und SLCT IN.

Kann jedem das Buch weiterempfehlen :allright:

MfG Falko
Bild
Win10 Pro 64-Bit, PB_5.4,GFA-WinDOS, Powerbasic9.05-Windows, NSBasic/CE, NSBasic/Desktop, NSBasic4APP, EmergenceBasic
Antworten