Ooops
November 25, 2020, 05:09:46 AM

Author Topic: [bb] Stepper Motor Control by jfk EO-11110 [ 1+ years ago ]  (Read 769 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Stepper Motor Control
Author : jfk EO-11110
Posted : 1+ years ago

Description : Get the sourcecode together with the required DLPORTIO.DLL and dlportio.decls from here:

<a href="http://www.melog.ch/cnc/smc800_io.zip" target="_blank">http://www.melog.ch/cnc/smc800_io.zip[/url]


Code :
Code: BlitzBasic
  1. ; ****************************************************************************************************
  2. ; ********************* CALLING THE SMC800 STEPPERMOTOR CONTROLLER FROM BLITZ3D **********************
  3. ; ****************************************************************************************************
  4.  
  5. ; This Program shows how to call the SMC800 Steppermotor Controller Card trough the Parallel Port.
  6. ; Other Controllers of the SMC Series may work with it too (SMC1500 etc.). See www.emis.com.
  7.  
  8. ; The SMC can control 3 Stepper Motors and one contact switch. The contact switch is used
  9. ; to self-calibrate the Machine. Each axis can travel to its Zero Point, defined by a contact switch.
  10. ; After reaching the contact switch it has to move back a certain amount of mm (again out of the contact
  11. ; zone), so it's possible to start each row of a CNC Raster Milling Process at pretty much
  12. ; the same loaction. The 3 Switches are simply wired parallel and connected to the SMC800.
  13. ; This allows to "home" each Motor individually. Warning: using the Function "MotorHome()"
  14. ; without working contact switches may cause your motors to seek for contact
  15. ; forever.
  16.  
  17. ; Unlike many other Control Cards, the SMC800 expects a rudimentary Amplitude Sinus Modulation for the
  18. ; two phases of the Steppermotors. It's really a good thing to study and understand stepper Motors.
  19. ; The card offers 800mA for each Phase only, the SMC1500 allows 1.5Amp. Motors must be Two Phase
  20. ; Stepper Motors, operating at the same voltage that the SMC's power supply provides, this may be
  21. ; 12 To 30 Volts.
  22.  
  23. ; The phase modulation can have a frequency up to 5 kHz. Due to the lack of programmable timers
  24. ; in Blitz3D we will use a Polling system here, based on the 1 kHz System Timer.
  25.  
  26.  
  27. ; The Comments in the Program explain the basic concept of calling the card in order to run
  28. ; a 3 Axis CNC Router/Locator. The following XYZ Convention is used:
  29.  
  30. ; X = Motor 0 (left / right)
  31. ; Y = Motor 1 (down / up)
  32. ; Z = Motor 2 (back / forward)
  33.  
  34. ; CNC People often name the vertical axis "Z", which is wrong from a scientific point of view.
  35. ; In this Demo "Y" is the vertical axis. You may alter this in the code if you prefere Z for the
  36. ; vertical axis.
  37.  
  38.  
  39.  
  40. ; In Addition to Blitz3D, a DLL is used, "DLPORTIO.dll" and also the blitz userlib "dlportio.decls",
  41. ; containing the following declarations:
  42.  
  43. ;.lib "dlportio.dll"
  44.  
  45. ;DlPortReadPortUchar%( port% )
  46. ;DlPortReadPortUshort%( port% )
  47. ;DlPortReadPortUlong%( port% )
  48.  
  49. ;DlPortReadPortBufferUchar( port%, buffer*, count% )
  50. ;DlPortReadPortBufferUshort( port%, buffer*, count% )
  51. ;DlPortReadPortBufferUlong( port%, buffer*, count% )
  52.  
  53. ;DlPortWritePortUchar( port%, value% )
  54. ;DlPortWritePortUshort( port%, value% )
  55. ;DlPortWritePortUlong( port%, value% )
  56.  
  57. ;DlPortWritePortBufferUchar( port%, buffer*, count% )
  58. ;DlPortWritePortBufferUshort( port%, buffer*, count% )
  59. ;DlPortWritePortBufferUlong( port%, buffer*, count% )
  60.  
  61. ; Special Thanks to the author of PortIO.dll for BLitz3D, right now I cannot find his name, not even
  62. ; in the original portio.zip, so please excuse.
  63.  
  64.  
  65.  
  66. ; This Demo Program is not a functional CNC Tool, it only shows how to call the
  67. ; Stepper Motors. Implementing a simple CNC Mill is pretty straight forward when
  68. ; you consider X and Z as the working space, and Y as the heights taken from a heightmap,
  69. ; pixel by pixel, or from a 3D scene using LinePick or CameraPick on a certain field of view.
  70.  
  71. ; You may however add usage of Start- and Stop-Speed for the stepper motors, because this
  72. ; will allow to operate a machine with less vibration and less material stress, including
  73. ; stress for the motors. There are several books and Websites about CNC programming.
  74.  
  75.  
  76. Graphics 800,600,32,2 ; set up graphics
  77. SetBuffer BackBuffer()
  78.  
  79.  
  80.  
  81. Global max_motor=2  ;(0=x, 1=y, 2=z)
  82.  
  83.  
  84. Dim invert_axis(max_motor) ; here you can easily reverse a motors logic (0=normal operation, 1=reverse operation)
  85. invert_axis(0)=1
  86. invert_axis(1)=0
  87. invert_axis(2)=0
  88. ;(these are the proxxon mf70 cnc settings)
  89.  
  90.  
  91. Global LPT=$378 ; this is the parallel port of your machine. The number may differ, see "Resources" in the device manager's parallel port settings.
  92.                 ; and/or Bios. Note: you may have to disable the "bidirectional" parallel port mode in the bios by choosing eg. "unidirectional".
  93.  
  94.  
  95. Dim phase_A(max_motor,8)    ; In these arrays we'll store the amplitude modulation curves
  96. Dim phase_B(max_motor,8)
  97. Dim phase_count#(max_motor) ; Used as modulation curves index
  98.  
  99.  
  100.  
  101.  
  102.  
  103. ; The SMC800 allows for 3 levels of power: 20%, 50% and 100%
  104. ; In fact this will only set the curves to something more flat.
  105. SetMotorPower(0,100) ; use 20, 50 or 100
  106. SetMotorPower(1,100)
  107. SetMotorPower(2,100)
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117. Global Special_msg$="" ; used to tell the user some infos
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125. ; Defining some standard speeds, where only the Reference Travel speed is used in this example.
  126. cnc_MainSpeed#=0.25
  127. cnc_StartSpeed#=0.125
  128. cnc_StopSpeed#=0.125
  129. cnc_RefSpeed#=0.5
  130. ; Note. these speeds represent the frequency in kHz. 1.0 is the max! Use a fraction of 1.0 (1.0, 0.5, 0.25, 0.2,  0.125 ...)
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137. ;************************************     Main Test Loop     ***************************************
  138. While KeyDown(1)=0
  139.  Cls
  140.  Text 0,0, "Cursor= left right, back , forward"
  141.  Text 0,16,"PgUp/Dn= up, down"
  142.  Text 0,32,"H= Home all Motors"
  143.  Text 0,48,"Esc= Exit"
  144.  Text 0,64, Special_msg$ ;  ; (Number of pulses for last MotorHome(): always Z axis in this demo, because it was the last one)
  145.  Flip
  146.  
  147.  ; manual control of the 3 Motors
  148.  k=203
  149.  If KeyDown(k)
  150.   While KeyDown(k)
  151.    sync_timer(cnc_RefSpeed#)
  152.    status = call_motor(0, 1) ; x minus
  153.   Wend
  154.  EndIf
  155.  k=205
  156.  If KeyDown(k)
  157.   While KeyDown(k)
  158.    sync_timer(cnc_RefSpeed#)
  159.    status = call_motor(0, 0) ; x plus
  160.   Wend
  161.  EndIf
  162.  k=208
  163.  If KeyDown(k)
  164.   While KeyDown(k)
  165.    sync_timer(cnc_RefSpeed#)
  166.    status = call_motor(2, 1) ; z minus
  167.   Wend
  168.  EndIf
  169.  k=200
  170.  If KeyDown(k)
  171.   While KeyDown(k)
  172.    sync_timer(cnc_RefSpeed#)
  173.    status = call_motor(2, 0) ; z plus
  174.   Wend
  175.  EndIf
  176.  k=209
  177.  If KeyDown(k)
  178.   While KeyDown(k)
  179.    sync_timer(cnc_RefSpeed#)
  180.    status = call_motor(1, 1) ; y minus
  181.   Wend
  182.  EndIf
  183.  k=201
  184.  If KeyDown(k)
  185.   While KeyDown(k)
  186.    sync_timer(cnc_RefSpeed#)
  187.    status = call_motor(1, 0) ; y plus
  188.   Wend
  189.  EndIf
  190.  
  191.  ; home...
  192.  k=35
  193.  If KeyHit(35) Then
  194.   ; (Note: it's neccessary to first Home the vertical motor!)
  195.   MotorHome(1,cnc_RefSpeed#)
  196.   MotorHome(0,cnc_RefSpeed#)
  197.   MotorHome(2,cnc_RefSpeed#)
  198.  EndIf
  199.  
  200. Wend
  201. End
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216. Function call_motor(motor, direction)
  217.  
  218.  ; motor choice: 0,1,2
  219.  ; direction: 0 (away from home) or 1 (back to home)
  220.  
  221.  
  222.  STB = LPT + 2 ; parallel port status port
  223.  stb_byte = inp(STB) ; (we need this later for a printerport handshake)
  224.  
  225.  ;*** assembling the data byte for the SMC ***
  226.  pc=Floor(phase_count(motor))
  227.  byte=(phase_A(motor,pc) Or phase_B(motor,pc))  Or (motor Shl 6)
  228.  
  229.  
  230.  ;*** Sending Data to Controller ***
  231.  outp(LPT, (byte))   ; Actually send the Amplitude data and Motor Selection
  232.  
  233.  
  234.  ; *** LPT Handshake ***
  235.  ;The following low level handshake may be a relict of needle printer times,
  236.  ;but it seems it's still neccessary with a lot of of parallel port devices,
  237.  ;such as this control card.
  238.  outp(STB, stb_byte Or 1) ; gotta do a quick handshake to the "printer"
  239.  ; eventually have to add a small delay here: (tho seems to work without it)
  240.  ; For i=0 To 1000
  241.  ; Next
  242.  outp(STB, stb_byte And (~1)) ; note: "~1" means "Not(1)", or simply "254"
  243.  ; end of LPT handshake
  244.  
  245.  
  246.  ; Increment/Loop Phase curve index
  247.  If direction=invert_axis(motor)
  248.   phase_count(motor)=phase_count(motor)+1.0
  249.   If phase_count(motor)>=8.0 Then phase_count(motor)=phase_count(motor)-8.0
  250.  Else
  251.   phase_count(motor)=phase_count(motor)-1.0
  252.   If phase_count(motor)<0.0 Then phase_count(motor)=phase_count(motor)+8.0
  253.  EndIf
  254.  
  255.  
  256.  
  257.  ; *** Checking the Contact Switch ***
  258.  ; At the IO Port LPT+1 we read the control byte of the parallel port. Bit number 8
  259.  ; will signal if the contact switch is closed or not:
  260.  ; Bit is set: no contact
  261.  ; Bit is zero: contact!
  262.  
  263.  CTR = LPT + 1 ; parallel port control port
  264.  ctr_byte = inp(CTR)
  265.  Return ctr_byte  ; bit 8 of this byte is the low active contact switch
  266. End Function
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274. ; Functions to utilize BIOS input/output, to access the printer port on the hardware level.
  275. Function outp(adress, value)
  276.  DlPortWritePortUchar(adress , value )
  277. End Function
  278.  
  279.  
  280. Function inp(adress)
  281.  value = DlPortReadPortUchar%( adress )
  282.  Return value
  283. End Function
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293. Function MotorHome(motor,speed#=0.5)
  294.  reached_ref=0
  295.  count_pulses=0
  296.  While reached_ref=0
  297.   ; drive slide to contact switch:
  298.   code=sync_timer(speed#) ; this will sync the motor calling with a certain frequency (Hz = speed * 1000)
  299.   If code=777 Then:Return code:EndIf ; (aborted by user?)
  300.   status = call_motor(motor, 1)
  301.   count_pulses=count_pulses+1
  302.   If (status And 128)=0  ;(reached contact switch ?)
  303.    While (status And 128)=0 ; drive a little back, again out of contact
  304.     code=sync_timer(speed#)
  305.     If code=777 Then:Return code:EndIf
  306.     status = call_motor(motor, 0)
  307.     count_pulses=count_pulses-1
  308.    Wend
  309.    counter=0
  310.    While counter<1600 ; add some extra mm (eg. ~2 turns with 1.8deg steppermotors and M5 lathe axis)
  311.     code=sync_timer(speed#)
  312.     If code=777 Then:Return code:EndIf
  313.     status = call_motor(motor, 0)
  314.     counter=counter+1
  315.     count_pulses=count_pulses-1
  316.    Wend
  317.    reached_ref=1
  318.   EndIf
  319.  Wend
  320.  Special_msg$="Last Motor Home required: "+ count_pulses +" Pulses." ; this is useful for metric calibrations!
  321.  Return 0
  322. End Function
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329. ; This function will wait for a certain while in order to synchronize
  330. ; the calling of the motors with the choosen speed (Hz=speed*1000)
  331. Function sync_timer(local_speed#=1.0)
  332.  secs=(1.0/local_speed#)-1
  333.  t=MilliSecs()+secs
  334.  While t >= MilliSecs()
  335.   If KeyDown(57) ; allow space key to abort things
  336.    Delay 200
  337.    FlushKeys()
  338.    Return 777  ; return some abort code
  339.   EndIf
  340.  Wend
  341.  Return 0 ; return zero for "successful execution"
  342. End Function
  343.  
  344.  
  345.  
  346.  
  347.  
  348. Function SetMotorPower(motor,power)
  349.  ; (For the Bits Description see also SMC800 Manual)
  350.  If motor<0 Then motor=0
  351.  If motor>max_motor Then motor=max_motor
  352.  
  353.  ; 20% power (set default anyway)
  354.  phase_A(motor,0)= %111
  355.  phase_A(motor,1)= %110
  356.  phase_A(motor,2)= %110
  357.  phase_A(motor,3)= %110
  358.  phase_A(motor,4)= %011
  359.  phase_A(motor,5)= %010
  360.  phase_A(motor,6)= %010
  361.  phase_A(motor,7)= %010
  362.  phase_A(motor,8)= phase_A(motor,0)
  363.  
  364.  phase_B(motor,0)= %110000
  365.  phase_B(motor,1)= %110000
  366.  phase_B(motor,2)= %011000
  367.  phase_B(motor,3)= %010000
  368.  phase_B(motor,4)= %010000
  369.  phase_B(motor,5)= %010000
  370.  phase_B(motor,6)= %111000
  371.  phase_B(motor,7)= %110000
  372.  phase_B(motor,8)= phase_B(motor,0)
  373.  
  374.  If power=50 Then
  375.   ; 50% power
  376.   phase_A(motor,0)= %111
  377.   phase_A(motor,1)= %101
  378.   phase_A(motor,2)= %101
  379.   phase_A(motor,3)= %101
  380.   phase_A(motor,4)= %011
  381.   phase_A(motor,5)= %001
  382.   phase_A(motor,6)= %001
  383.   phase_A(motor,7)= %001
  384.   phase_A(motor,8)= phase_A(motor,0)
  385.  
  386.   phase_B(motor,0)= %101000
  387.   phase_B(motor,1)= %101000
  388.   phase_B(motor,2)= %011000
  389.   phase_B(motor,3)= %001000
  390.   phase_B(motor,4)= %001000
  391.   phase_B(motor,5)= %001000
  392.   phase_B(motor,6)= %111000
  393.   phase_B(motor,7)= %101000
  394.   phase_B(motor,8)= phase_B(motor,0)
  395.  EndIf
  396.  If power=100 Then
  397.   ; 100% power
  398.   phase_A(motor,0)= %111
  399.   phase_A(motor,1)= %100
  400.   phase_A(motor,2)= %100
  401.   phase_A(motor,3)= %100
  402.   phase_A(motor,4)= %011
  403.   phase_A(motor,5)= %000
  404.   phase_A(motor,6)= %000
  405.   phase_A(motor,7)= %000
  406.   phase_A(motor,8)= phase_A(motor,0)
  407.  
  408.   phase_B(motor,0)= %100000
  409.   phase_B(motor,1)= %100000
  410.   phase_B(motor,2)= %011000
  411.   phase_B(motor,3)= %000000
  412.   phase_B(motor,4)= %000000
  413.   phase_B(motor,5)= %000000
  414.   phase_B(motor,6)= %111000
  415.   phase_B(motor,7)= %100000
  416.   phase_B(motor,8)= phase_B(motor,0)
  417.  EndIf
  418.  
  419. End Function


Comments :


M2PLAY(Posted 1+ years ago)

 WOUUUU!!! Amazing system. Good stuff!!!Thanks


Wayne(Posted 1+ years ago)

 Great stuff jfk!


Blitzplotter(Posted 1+ years ago)

 outrageous, this sort of real world integration is very interesting. now to find a cnc milling machine....


jfk EO-11110(Posted 1+ years ago)

 Note the code only works with SMC type controllers. Other systems may even be simpler (they usually take only direction and speed parameters and generate the amplitude curves by their own, onboard).There is one thing you should know about CNC, before you buy a machine: it takes many hours to make a single artpiece, especialy when you are using some kind of 3D raster milling application. Then again, it's great fun to drink a coffee while the machine is doing a lot of physical precision work.The mentioned Proxxon is best used for tiny things. Max travel is 162 * 84 * 86 mm (XYZ). See here:<a href="http://www.usovo.de/" target="_blank">http://www.usovo.de[/url]An other nice mill is the Taig CNC. Tho, shipping costs from the US to Europe was too high for me.I can only suggest to look around for a while, there are plenty cheap mills (near 2k$), but it takes some time to find them all.Here's however a comparation table:<a href="http://www.desktopcnc.com/mill_table.htm" target="_blank">http://www.desktopcnc.com/mill_table.htm[/url]PS additional Note for people who want to use this code with the Proxxon MF70 CNC by usovo.de : The machine has a built in relay to start/stop the drill motor. It can be triggered with bit 2 (value $02) on the status port (LPT+2). Note you have to OR the handshake byte-output in call_motor() with the desired/required drill motor state.PS2: The axis inverter array is now set to the proxxon motors layout, although in the zipfile it's still the old example. You may however carefully test your motors axes with the manual controls (cursor keys, PgUp/Dn) and edit the source until the motors act as desired BEFORE you hit "h" that will (try to) home all motors.


Danny(Posted 1+ years ago)

 Wicked stuff jfk!!Compliments!


LAB[au](Posted 1+ years ago)

 Yep nice work! I have the same machine (proxxon modded by Usovo) . I use it to make pcb and to engrave aluminium, until now I have used the recommended app for control (WinPCNC lite), now I could start to drive it more algorythmically :)Thanks for the release.


jhocking(Posted 1+ years ago)

 Whoah this is very cool.  I'm interested in exploring different kinds of IO with Blitz, so this work that you are doing is great to see.


Andres(Posted 1+ years ago)

 Is it possible to control the pins of LPT with something like that? I'd like to advance my PC-timer or control text on LCD from a calculator.


jfk EO-11110(Posted 1+ years ago)

 Yes sure simply use the portio.dll and decls that is part of the zipfile. You'll use the function INP and OUTP to write bytes to port adresses, such as your LPT port (see bios). The bits represent the pins (at least for the 8 Data bits). There are other ports, such as the LPT control port and status port,  with bits that are organized slightly diffrent. You'll find some infos about pins and bits in the web. This one, although german, may be useful: <a href="http://www.netzmafia.de/skripten/hardware/rp1/rp12.html" target="_blank">http://www.netzmafia.de/skripten/hardware/rp1/rp12.html[/url]


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal