Metal lathe control

lewisg

Senior Member
1st - this is NOT a full blown CNC lathe control!

This project has two modes of operation, drive the carriage using a stepper motor and display RPM/SFM. It is very helpful to me for reducing stock diameter, making sets of spacers all the same length and other operations.

IMG_8185.jpgIMG_8172.jpg

The first photo is of the control head. The button functions from left are:

Stop - in stepper mode stop moving the carriage, in RPM/SFM reset the workpiece diameter.
<< - in stepper mode move the carriage left or decrement carriage movement distance, in RPM/SFM decrement the workpiece diameter.
>> - in stepper mode move the carriage right or increment carriage movement distance, in RPM/SFM increment the workpiece diameter.
Prog Mode - (stepper mode only) step through the possible program modes: Free Run, Prog Left, Prog Right, Prog Left with Tool
Prog Run - (stepper mode only) start the selected program mode running.

The second photo shows the inside of the control box. This project uses a AXE401 board and a Seed Studio Motor Shield to minimize development time. All connections are out of the interfacing manual except for the large red & green buttons, the pot and relay on the left side. These control the lathe motor via a Variable Frequency Drive. Currently they have no connection to the Picaxe. In the future I will replace the micro switch on the big red stop button to include contacts to stop the stepper motor via the Picaxe.



The code is in multiple sections due to forum limitations.

Code:
# picaxe 28x2

' Metal lathe control and display program
' 2 modes of operation, drive the carriage using a stepper motor and display RPM/SFM
' 
' Bipolar stepper motor lathe carriage feed
' Seeedstudio Arduino Motor Shield v1 (C.1 & C.2 held high to enable)
' Left and Right are as viewed from front of motor 1=Red(A),2=Blue(-A),3=Green(B),4=Black(-B)
' Left is toward the headstock
' 1000 steps = .076" (+-.0015") so 1 step = .000076275"
' Sparkfun ADM1602U 2x16 serial LCD
'
' Revolutions Per Minute / Surface Feet per Minute use a hall effect (US5881LUA) sensor
' SFM calculation uses a user entered work piece diameter 

symbol LCDpin   = A.1
symbol StopPin  = pinA.0
symbol LeftPin  = pinA.2
symbol RightPin = pinA.3
symbol ProgPin  = pinB.3  'marked a4 on board
symbol RunPin   = pinB.4  'marked a5 on board
symbol HallPin  = B.0     'marked d3 on board - hall efect sensor
symbol ModePin  = pinB.1  'marked d4 on board - RPM&SFM or stepper mode

symbol StepVar1 = b0      'counter for stepper motor subroutine
symbol StepVar2 = b1      'output var to set pins for stepper motor subroutine
symbol LoopVar1 = w1      'starting value for programmed run loops starts at 0
symbol LoopVar2 = w2      'ending value for programmed run loops in steps
symbol ProgVar1 = w3      'how far to run in program mode, (currently in .01" resolution?)
symbol SlopStep = w4      'number of steps to run when reversing direction
symbol ToolWidth= w5      'width of tool in steps
symbol StepCount= w6      'count of steps run in free run mode
symbol RPM      = w7      'Revolutions Per Minute
symbol SFM      = w8      'Surface Feet per Minute
symbol StepConst= w9      'thousandths per 1000 steps
symbol ProgMode = b20     '0=free run,1=prog left,2=prog right,3=prog left with tool,4=RPM/SFM
symbol RunDir   = b21     '1=left 2=right
symbol Dis10000 = b22     'BinToASCII display variable
symbol Dis1000  = b23     'BinToASCII display variable      
symbol Dis100   = b24     'BinToASCII display variable
symbol Dis10    = b25     'BinToASCII display variable
symbol Dis1     = b26     'BinToASCII display variable
symbol FirstRun = b27     'skip ProgMode 4 and above after first loop
symbol ModeChng = b28     'detect change of mode from RPM/SFM vs stepper mode
symbol Dia      = w15     'diameter for SFM calc, 0.1 resolution
symbol Mark     = w16     'mark time of hall sensor for RPM calc 
symbol Space    = w17     'space time of hall sensor for RPM calc
      

'used for double word division
symbol topbit   = $8000   ; Value of "carry" bit (when shifting left)
symbol pass     = b49     ; Loop counter, on return = 0 if data error
symbol numhi    = w25     ; Numerator Hi, Returns Remainder
symbol numlo    = w26     ; Numerator Lo, Retuns Result
symbol divis    = w27     ; Divisor (max 15 bits), Unchanged on Return


ProgVar1 = 30             'starting value for programed runs (0.030)
ProgMode = 0              '0=free run,1=prog left,2=prog right,3=prog left with tool
SlopStep = 734            'number of steps to run when reversing direction
ToolWidth= 725            'steps for tool width (725 for .0625 cutoff)
StepConst= 76             'steps per 0.001
FirstRun = 0              'allow changes to SlopStep, ToolWidth & StepConst on first run through ProgMode
ModeChng = 0              'refresh LCD when stepper vs RPM/SFM mode changes
Dia      = 500            'starting value for diameter for SFM calc (0.200)

dirsC = %11111111         'setup output pins for stepper motor

pause 1000
serout LCDpin, t9600_8,(254,124,"<control>r")
serout LCDpin, t9600_8,(254,128,"Stepper14.bas    ")
serout LCDpin, t9600_8,(254,192,"LG 07/02/2013   ") 
pause 5000
serout LCDpin, t9600_8,(254,128,"Free Run Mode   ")
serout LCDpin, t9600_8,(254,192,"Ready           ") 


main: 

  if ModePin = 0 then           'stepper control
  
    if ModeChng = 1 then        'refresh LCD when changing from RPM/SFM mode
      serout LCDpin, t9600_8,(254,124,"<control>r")
      gosub DisplayProgMode
      ModeChng = 0
    end if

  
    if LeftPin = 1 then         'pin starts free run left AND increments ProgVar1 depending on ProgMode
      pause 200
      if ProgMode = 0 then
        StepCount = 0
        serout LCDpin, t9600_8,(254,192,"Running Left    ")
        do 
          gosub lstep
          StepCount = StepCount + 1
          if StopPin = 1 then
            BinToASCII StepCount,Dis10000,Dis1000,Dis100,Dis10,Dis1
            serout LCDpin, t9600_8,(254,192,"Stop ",Dis10000,Dis1000,Dis100,Dis10,Dis1," steps")
            exit
          end if      
        loop
        RunDir = 1
      else if ProgMode > 0 then
        if ProgVar1 > 1 then
          ProgVar1 = ProgVar1 - 1
        end if  
        BinToASCII ProgVar1,Dis10000,Dis1000,Dis100,Dis10,Dis1
        if ProgMode = 1 then 
          serout LCDpin, t9600_8,(254,128,"Prog Left: ",Dis1000,".",Dis100,Dis10,Dis1)
        else if ProgMode = 2 then 
          serout LCDpin, t9600_8,(254,128,"Prog Right:",Dis1000,".",Dis100,Dis10,Dis1)
        else if ProgMode = 3 then 
          serout LCDpin, t9600_8,(254,128,"P L w/tool:",Dis1000,".",Dis100,Dis10,Dis1)
        end if
      end if
    end if
    
    
    if RightPin = 1 then        'pin starts free run right AND decrements ProgVar1 depending on ProgMode  
      pause 200
      if ProgMode = 0 then
        StepCount = 0
        serout LCDpin, t9600_8,(254,192,"Running Right   ")
        do 
          gosub rstep
          StepCount = StepCount + 1
          if StopPin = 1 then
            BinToASCII StepCount,Dis10000,Dis1000,Dis100,Dis10,Dis1
            serout LCDpin, t9600_8,(254,192,"Stop ",Dis10000,Dis1000,Dis100,Dis10,Dis1," steps")
            exit
          end if      
        loop
        RunDir = 2
      else if ProgMode > 0 then
        ProgVar1 = ProgVar1 + 20
        BinToASCII ProgVar1,Dis10000,Dis1000,Dis100,Dis10,Dis1
        if ProgMode = 1 then 
          serout LCDpin, t9600_8,(254,128,"Prog Left: ",Dis1000,".",Dis100,Dis10,Dis1)
        else if ProgMode = 2 then 
          serout LCDpin, t9600_8,(254,128,"Prog Right:",Dis1000,".",Dis100,Dis10,Dis1)
        else if ProgMode = 3 then 
          serout LCDpin, t9600_8,(254,128,"P L w/tool:",Dis1000,".",Dis100,Dis10,Dis1)    
        end if      
      end if    
    end if
    
    
    if ProgPin = 1 then         'pin increments ProgMode variable
      pause 500
      
      if FirstRun = 0 then
        if ProgMode < 6 then
          ProgMode = ProgMode + 1
        else 
          ProgMode = 0
          FirstRun = 1  
        end if
      else if FirstRun = 1 then
        if ProgMode < 3 then
          ProgMode = ProgMode + 1
        else 
          ProgMode = 0  
        end if      
      end if  
      
      gosub DisplayProgMode   'refresh LCD
      
    end if

'*** CONTINUED NEXT POST ***
 
Last edited:

lewisg

Senior Member
More lathe

IMG_8170.jpgIMG_8177.jpg

How the Hall sensor and stepper motor are attached to the lathe.

The sub procedures will have to be in the next post...

Code:
'*** CONTINUED FROM PREVIOUS POST ***

    if RunPin = 1 then        'pin initiates selected prog mode
      pause 200 
      
      if ProgMode = 1 OR ProgMode = 2 OR ProgMode = 3 then
        BinToASCII ProgVar1,Dis10000,Dis1000,Dis100,Dis10,Dis1
        if ProgMode = 1 then 
          serout LCDpin, t9600_8,(254,128,"Prog Left: ",Dis1000,".",Dis100,Dis10,Dis1)
          if RunDir = 2 then
            serout LCDpin, t9600_8,(254,192,"Removing Slop   ")
            for LoopVar1 = 0 to SlopStep
              gosub lstep
            next LoopVar1
            RunDir = 1
          end if
        else if ProgMode = 2 then 
          serout LCDpin, t9600_8,(254,128,"Prog Right:",Dis1000,".",Dis100,Dis10,Dis1)
          if RunDir = 1 then
            serout LCDpin, t9600_8,(254,192,"Removing Slop   ")
            for LoopVar1 = 0 to SlopStep
              gosub rstep
            next LoopVar1
            RunDir = 2
          end if
        else if ProgMode = 3 then 
          serout LCDpin, t9600_8,(254,128,"P L w/tool:",Dis1000,".",Dis100,Dis10,Dis1)    
          if RunDir = 2 then
            serout LCDpin, t9600_8,(254,192,"Removing Slop   ")
            for LoopVar1 = 0 to SlopStep
              gosub lstep
            next LoopVar1
            RunDir = 1
          end if
        end if
    
        LoopVar2 = 0                  'set the number of steps the motor will run by
        numhi = ProgVar1 ** 1000      'dividing the distance in thousandths by how far 
        numlo = ProgVar1 * 1000       '1000 steps of the stepper moves the tool
        divis = StepConst
        gosub div31v
        if pass <> 0 then
          LoopVar2 = numlo
        else
          serout LCDpin, t9600_8,(254,192,"Division ERROR  ")
          pause 5000
        end if
        
        if LoopVar2 <> 0 then
          if ProgMode = 3 then
            LoopVar2 = LoopVar2 + ToolWidth   'steps for tool width (725 for .0625 cutoff)
          end if
          
          BinToASCII LoopVar2,Dis10000,Dis1000,Dis100,Dis10,Dis1
          serout LCDpin, t9600_8,(254,192,"Run ",Dis10000,Dis1000,Dis100,Dis10,Dis1," steps ")    
          
          for LoopVar1 = 0 to LoopVar2
            if ProgMode = 1 or ProgMode = 3 then
              gosub lstep
            else if ProgMode = 2 then
              gosub rstep
            end if  
            if StopPin = 1 then
              serout LCDpin, t9600_8,(254,192,"** User  Stop **")
              pause 5000
              exit
            end if
          next LoopVar1
        
          if ProgMode = 1 or ProgMode = 3 then
            RunDir = 1
          else if ProgMode = 2 then
            RunDir = 2
          end if    
        
          serout LCDpin, t9600_8,(254,192,"End ",Dis10000,Dis1000,Dis100,Dis10,Dis1," steps ")
        endif   
      else
        serout LCDpin, t9600_8,(254,192,"Not in Prog Mode")
      end if
    end if
  
  else if ModePin = 1 then            'RPM/SFM readout
  
    if ModeChng = 0 then              'refresh LCD when changing from stepper control mode
      serout LCDpin, t9600_8,(254,124,"<control>r")
      BinToASCII Dia,Dis10000,Dis1000,Dis100,Dis10,Dis1
      serout LCDpin, t9600_8,(254,128,"DIA:",Dis1000,".",Dis100,Dis10,Dis1,"       ")
      serout LCDpin, t9600_8,(254,192,  "RPM:",Dis1000,Dis100,Dis10,Dis1)
      serout LCDpin, t9600_8,(254,200,  " SFM:",Dis100,Dis10,Dis1)
      ModeChng = 1
    end if
    
    if LeftPin = 1 then               'increment, decrement or reset Dia variable
      if Dia > 100 then
        Dia = Dia - 100
      end if    
      BinToASCII Dia,Dis10000,Dis1000,Dis100,Dis10,Dis1
      serout LCDpin, t9600_8,(254,128,"DIA:",Dis1000,".",Dis100,Dis10,Dis1,"       ")
    else if RightPin = 1 then
      if Dia < 6100 then
        Dia = Dia + 100
      end if
      BinToASCII Dia,Dis10000,Dis1000,Dis100,Dis10,Dis1
      serout LCDpin, t9600_8,(254,128,"DIA:",Dis1000,".",Dis100,Dis10,Dis1,"       ")
    else if StopPin = 1 then
      Dia = 500
      BinToASCII Dia,Dis10000,Dis1000,Dis100,Dis10,Dis1
      serout LCDpin, t9600_8,(254,128,"DIA:",Dis1000,".",Dis100,Dis10,Dis1,"       ")   
    end if  
    
'   count HallPin, 2500, RPM      'pulses in second
'   RPM = RPM * 60                'pulses in 1 minute

    Setfreq M4
    pulsin HallPin, 1, Mark
    pulsin HallPin, 0, Space
    Setfreq M8

    sertxd (#mark,",",#space)
    
    if Space < 4000 then
      RPM = Mark + Space          'get the rotation period
      RPM = RPM / 100             'convert period to ms
      RPM = 60000 / RPM 
      sertxd (",",#mark,",",#space,",",#RPM,", H",cr,lf)    
    else                          'low RPMs
      Space = Space / 10
      Mark = Space * 14
      RPM = Mark + Space
      RPM = 60000 / RPM   
      RPM = RPM * 10
      sertxd (",",#mark,",",#space,",",#RPM,", L",cr,lf)      
    end if

    BinToASCII RPM,Dis10000,Dis1000,Dis100,Dis10,Dis1
    serout LCDpin, t9600_8,(254,192,  "RPM:",Dis1000,Dis100,Dis10,Dis1)

    SFM = Dia *10 **17158         'marks - even better!
    SFM = rpm *8 **53687 **sfm    

    BinToASCII SFM,Dis10000,Dis1000,Dis100,Dis10,Dis1
    serout LCDpin, t9600_8,(254,200,  " SFM:",Dis100,Dis10,Dis1)

    pause 100

  end if

goto main

'*** SUB PROCEDURES IN NEXT POST ***
 
Last edited:

lewisg

Senior Member
Lathe wrap up

Here are the sub procedures:

Code:
'*** CONTINUED FROM LAST POST ***

DisplayProgMode:

      if ProgMode = 0 then
        serout LCDpin, t9600_8,(254,128,"Free Run Mode   ")
        serout LCDpin, t9600_8,(254,192,"Ready           ")
        
      else if ProgMode = 1 then
        BinToASCII ProgVar1,Dis10000,Dis1000,Dis100,Dis10,Dis1
        serout LCDpin, t9600_8,(254,128,"Prog Left: ",Dis1000,".",Dis100,Dis10,Dis1)
        serout LCDpin, t9600_8,(254,192,"Ready           ")
                  
      else if ProgMode = 2 then
        BinToASCII ProgVar1,Dis10000,Dis1000,Dis100,Dis10,Dis1
        serout LCDpin, t9600_8,(254,128,"Prog Right:",Dis1000,".",Dis100,Dis10,Dis1)
        serout LCDpin, t9600_8,(254,192,"Ready           ")
        
      else if ProgMode = 3 then
        BinToASCII ProgVar1,Dis10000,Dis1000,Dis100,Dis10,Dis1
        serout LCDpin, t9600_8,(254,128,"P L w/tool:",Dis1000,".",Dis100,Dis10,Dis1)
        serout LCDpin, t9600_8,(254,192,"Ready           ")
        
      else if ProgMode = 4 then 
        serout LCDpin, t9600_8,(254,128,"Set Tool Width  ")
        do
          BinToASCII ToolWidth,Dis10000,Dis1000,Dis100,Dis10,Dis1
          serout LCDpin, t9600_8,(254,192,"Tool:",Dis1000,Dis100,Dis10,Dis1," steps ")      
          if LeftPin = 1 then
            if ToolWidth > 1 then
              ToolWidth = ToolWidth - 1
            end if
          end if
          if RightPin = 1 then
            ToolWidth = ToolWidth + 1   
          end if
          if ProgPin = 1 then
            pause 100
            exit
          end if
          pause 100  
        loop

      else if ProgMode = 5 then 
        serout LCDpin, t9600_8,(254,128,"Set Slop Steps  ")
        do
          BinToASCII SlopStep,Dis10000,Dis1000,Dis100,Dis10,Dis1
          serout LCDpin, t9600_8,(254,192,"Slop:",Dis1000,Dis100,Dis10,Dis1," steps ")      
          if LeftPin = 1 then
            if SlopStep > 1 then
              SlopStep = SlopStep - 1
            end if
          end if
          if RightPin = 1 then
            SlopStep = SlopStep + 1   
          end if
          if ProgPin = 1 then
            pause 100
            exit
          end if
          pause 100  
        loop
        
      else if ProgMode = 6 then 
        serout LCDpin, t9600_8,(254,128,"Set StepConstant")
        do
          BinToASCII StepConst,Dis10000,Dis1000,Dis100,Dis10,Dis1
          serout LCDpin, t9600_8,(254,192,"1000step=.",Dis1000,Dis100,Dis10,Dis1,"in")      
          if LeftPin = 1 then
            if StepConst > 1 then
              StepConst = StepConst - 1
            end if
          end if
          if RightPin = 1 then
            StepConst = StepConst + 1   
          end if
          if ProgPin = 1 then
            pause 100
            exit
          end if
          pause 100  
        loop        
        
      end if  
      
return      



'drive stepper motor from PICAXE manual 3 page 17
  
lstep: 
  StepVar1 = StepVar1 + 1
  goto step2

rstep:
  StepVar1 = StepVar1 - 1
  goto step2

step2:
  StepVar1 = StepVar1 & %00000011                               ; mask lower two bits of StepVar1
                                                                ; (resets StepVar1 @ 4 and 0)
  lookup StepVar1,(%010111,%001111,%101110,%110110),StepVar2
  pinsC = StepVar2                                              ; output StepVar2 onto control lines
return


; Divide Double-Word (w3:w2) by w1 using binary Long Division
; w2 = Result; w3 = Remainder; w1 unchanged; b0 = 0 if input error
; Max divisor 32767 (15 bits), max result 65535 (16 bits)
; AllyCat  15th June 2012
' www.picaxeforum.co.uk/showthread.php?21494

div31v:                         ; Validate data and Divide numerator by divisor
  pass = 0                      ; Pre-set the error marker
  if divis => topbit OR numhi >= divis then done    ; Data Error so quit    
div31:                          ; Enter here to Divide with NO error check
  for pass =  0 to 15           ; Repeat for each bit position
  numhi = numhi + numhi         ; Start to shift numerator left (top bit is lost)
  if numlo >= topbit then       ; Carry bit from low word is '1'
    numhi = numhi + 1           ; Add the carry to hi word
    endif
  numlo = numlo + numlo         ; End of Shift
  if numhi < divis then nosub   ; Jump if can't subtract
  numhi = numhi - divis         ; Subtract divisor and ...        
  numlo = numlo + 1             ; Add the flag to result (in low word)
nosub:    
  next pass
done:
return
Without this forum I could not have done this project. AllyCat's double word division was essential to get meaningful accuracy for the stepper over a non trivial distance. Goeytex and Marks both provided much needed help in the Active PICAXE Forum thread Help with tachometer.

I hope this project is useful to someone...
 
Top