CNC manual controller
The CNC manual controller.

Here a design of my manual CNC controller for my MF70 PROXXON milling machine.
This design is based on a 16F877 controller, programmed in PROTON PICBASIC.
Steprate and feedrate are adjustable. The stepper motors that are used are NEMA17 type's and need 200 pulses for one 1 revolution, and as the PROXXON needs one turn for one mm of displacement, it's 200 steps equals 1mm.


I use the grbl software on an arduino to control my milling machine for processing regular G-code.
As for very simple and small milling works it takes more time to draw and export a task, I want to control the machine manually. Instead of counting the dials, I let a microcontroller control the stepper motors.
When you push a button, according to the adjustable steprate, the micrcontroller receives a request to move for e.g. 1mm, it will give 200 pulses to that stepper motor driver.
Also the feedrate is adjustable, so you can specify how fast the steppermotors must go.

'****************************************************************
'*  Name    : CNC_CONTROLLER.BAS                                *
'*  Author  : TDCBYTE                                           *
'*  Notice  : Copyright (c) 2017 TDCBYTE                        *
'*          : All Rights Reserved                               *
'*  Date    : 1/12/2017                                         *
'*  Version : 1.0                                               *
'*  Notes   : TMR0 zal voor de interrupt zorgen voor periodiek  *
'*          : uitvoeren van de code, die tijdskritisch is.      *
'****************************************************************

Device = 16F877
   
Xtal = 20    
   
All_Digital = TRUE
   
     
'Configuratie voor programmer
   
Config CP_OFF,DEBUG_OFF,CPD_OFF,LVP_OFF,BODEN_OFF,PWRTE_ON,WDT_OFF,HS_OSC
   
Reminders On
          
'Include "PICD_Monitor.inc"
          ' Enable Debug

    
   
TRISA = %00000000      '0 = output
   
TRISB = %00000000      '0 = output
   
TRISC = %11111111      '1=INPUT
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
   
Symbol RBIF = INTCON.0 ' RB Port Interrupt Flag
   
Symbol INTF = INTCON.1 ' RB0 External Interrupt Flag
   
Symbol T0IF = INTCON.2 ' TMR0 Overflow Interrupt Flag
   
Symbol RBIE = INTCON.3 ' RB Port Change Interrupt Enable
   
Symbol INTE = INTCON.4 ' RB0 External Interrupt Enable
   
Symbol T0IE = INTCON.5 ' TMR0 Overflow Interrupt Enable
   
Symbol PEIE = INTCON.6 ' Peripheral Interrupt Enable
   
Symbol GIE = INTCON.7  ' Global Interrupt Enable


   
Symbol PS0 = OPTION_REG.0      ' Prescaler Rate Select
   
Symbol PS1 = OPTION_REG.1      ' Prescaler Rate Select
   
Symbol PS2 = OPTION_REG.2      ' Prescaler Rate Select
   
Symbol PSA = OPTION_REG.3      ' Prescaler Assignment
   
Symbol T0SE = OPTION_REG.4     ' TMR0 Source Edge Select
   
Symbol T0CS = OPTION_REG.5     ' TMR0 Clock Source Select
   
Symbol INTEDG = OPTION_REG.6   ' Interrupt Edge Select
   
Symbol NOT_RBPU = OPTION_REG.7 ' PORTB Pull-up Enable
    
   
Symbol DOXPULSE = PORTA.0       'OUTPUT VOOR X-as pulsen
   
Symbol DOXDIR = PORTA.1         'OUTPUT VOOR X-as draairichting
   
Symbol DOYPULSE = PORTA.2       'OUTPUT VOOR Y-as pulsen
   
Symbol DOYDIR = PORTA.3         'OUTPUT VOOR Y-as draairichting
   
Symbol DOZPULSE = PORTA.4       'OUTPUT VOOR Z-as pulsen
   
Symbol DOZDIR = PORTA.5         'OUTPUT VOOR Z-as draairichting
   
   
Symbol DOINT = PORTB.0          'OUTPUT VOOR INTERRUPT CYCLE TIJDSMETING (DEBUGGING ONLY)
   
Symbol DOMAIN = PORTB.1         'OUTPUT VOOR MAIN CYCLE TIJDSMETING  (DEBUGGING ONLY)
   
   
Symbol DIROT1 = PORTC.0         'INPUT VOOR ROTARY ENCODER  PIN 1
   
Symbol DIROT2 = PORTC.1         'INPUT VOOR ROTARY ENCODER PIN 2
   
Symbol DIROTPUSH = PORTC.2      'INPUT VOOR INDRUKKEN VAN ROTARY ENCODER   
   
   
Symbol DIXADD = PORTC.3         'INPUT X axis +
   
Symbol DIXSUB = PORTD.0         'INPUT X axis -
   
Symbol DIXZERO = PORTD.1        'INPUT X axis "0"
   
   
Symbol DIZZERO = PORTD.2        'INPUT Z axis +
   
Symbol DIZSUB = PORTD.3         'INPUT Z axis -
   
Symbol DIZADD = PORTC.4         'INPUT Z axis "0"
   
   
Symbol DIYZERO = PORTC.5        'INPUT Y axis +
   
Symbol DIYSUB = PORTD.4         'INPUT Y axis -
   
Symbol DIYADD = PORTD.5         'INPUT Y axis "0"
   
   
Symbol DISTOP = PORTD.6         'INPUT STOP ALLE ACTIES
     
   
Symbol FALSE = 0   
    Symbol TRUE = 1   
   

    Declare
LCD_DTPin = PORTB.4      'LCD DECLARATIE, standaard HD44780 interface
Declare LCD_RSPin = PORTB.3
Declare
LCD_ENPin = PORTB.2
Declare
LCD_Interface = 4
Declare
LCD_Lines = 4            ' !! 4 lijnig lcd
Declare LCD_Type = 0
        
        
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    'Declareer hier alle variabelen.
   
    'Geheugen voor druknnoppen
   
Dim  BTNVARRPUSH As Byte
   
BTNVARRPUSH = 0
          
    Dim BTNVARXADD As Byte
   
BTNVARXADD = 0 
  
    Dim BTNVARXSUB As Byte
   
BTNVARXSUB = 0 
   
    Dim BTNVARXZERO As Byte
   
BTNVARXZERO = 0 
    
    Dim BTNVARYADD As Byte
   
BTNVARYADD = 0 
  
    Dim BTNVARYSUB As Byte
   
BTNVARYSUB = 0 
   
    Dim BTNVARYZERO As Byte
   
BTNVARYZERO = 0
   
    Dim BTNVARZADD As Byte
   
BTNVARZADD = 0 
  
    Dim BTNVARZSUB As Byte
   
BTNVARZSUB = 0 
   
    Dim BTNVARZZERO As Byte
   
BTNVARZZERO = 0   
       
  
  
'Interne logica  
   ' 
    
Dim VARFEEDRATE As Byte     '0-15 stappen
    
VARFEEDRATE = 10 'Default 10
    
Dim VARFEEDRATEPOW2 As Byte  ' product van VARFEEDRATE, zo krijgen we bij elke stap een verdubbeling van tijd
    
Dim FEEDRATECOUNTER As Byte  'Teller om acties op te triggeren
    
    
    
    
Dim STEPSIZEARRAY [6] As Word  'Array voor ingestelde Steprate's
       
STEPSIZEARRAY[0] = 20
        STEPSIZEARRAY[1] = 100
        STEPSIZEARRAY[2] = 200
        STEPSIZEARRAY[3] = 1000
        STEPSIZEARRAY[4] = 2000
        STEPSIZEARRAY[5] = 10000
       
    Dim STEPSIZEARRAYP1[6] As Byte 
'Array voor steprate in mm weer te geven, alles hardcoded, zodat we niets moeten berekenen. Keep it simple
       
STEPSIZEARRAYP1[0]  = 1    '0.1mm
       
STEPSIZEARRAYP1[1]  = 5    '0.5mm
       
STEPSIZEARRAYP1[2]  = 0    '1.0mm
       
STEPSIZEARRAYP1[3]  = 0    '5.0mm
       
STEPSIZEARRAYP1[4]  = 0    '10.0mm
       
STEPSIZEARRAYP1[5]  = 0    '50.0mm
       
    
Dim STEPSIZEARRAYP2[6] As Byte   'deel 2 voor Array voor steprate in mm weer te geven, alles hardcoded, zodat we niets moeten berekenen. Keep it simple
       
STEPSIZEARRAYP2[0]  = 0    '0.1mm
       
STEPSIZEARRAYP2[1]  = 0    '0.5mm
       
STEPSIZEARRAYP2[2]  = 1    '1.0mm
       
STEPSIZEARRAYP2[3]  = 5    '5.0mm
       
STEPSIZEARRAYP2[4]  = 10   '10.0mm
       
STEPSIZEARRAYP2[5]  = 50   '50.0mm

     
    
    
Dim VARSTEPSIZE As Word       'Wordt gebruikt voor effectieve berekening van de pulsen
         
VARSTEPSIZE = 2 'default 1mm
    
Dim STEPSIZESELECTION As Byte 'van 1 tot 6 wat gebruiker kan kiezen.
    
    'variabelen voor rotary encoder.   
    
Dim ROTFIRST As Byte
    
ROTFIRST = 0   
     Dim Pflank As Bit
     Dim
Pflank2 As Bit
    
     Dim
ROTSEL As Bit   
'Selectie of we me de draaiknop de feedrate of de steprate gaan instellen
    
Dim ARROW As Byte
 
  
'Hier variabelen per as.
  
 
   
Dim XaxisJobCounter As Word     'X axis job counter
    
XaxisJobCounter = 0
    Dim XaxisJobCounterNeg As Bit  
'X axis if setpoint is negative
    
XaxisJobCounterNeg = 0
    
    Dim XaxisPosPulse As SDword 
'Effectieve positie van de as in pulsen (meest correcte plaatsbepaling)
   
Dim XaxisPosP1 As SDword    'Positie1 zijn de milimeters op scherm
   
Dim XaxisPosP2 As Dword    'Positie2 zijn de tienden van een milimeter op scherm
   
Dim XaxisPosNeg As Byte   'De Xas positief of negatief symbool
   
   
Dim XaxisZeroRequest As Bit
   

  
    Dim
YaxisJobCounter As Word    
'Y axis job counter
    
YaxisJobCounter = 0
    Dim YaxisJobCounterNeg As Bit  
'Y axis if setpoint is negative
    
YaxisJobCounterNeg = 0         'Positie2 zijn de tienden van een milimeter op scherm
   
   
Dim YaxisPosPulse As SDword  'Effectieve positie van de as in pulsen (meest correcte plaatsbepaling)
   
Dim YaxisPosP1 As SDword    'Positie1 zijn de milimeters op scherm
   
Dim YaxisPosP2 As Dword    'Positie2 zijn de tienden van een milimeter op scherm
   
Dim YaxisPosNeg As Byte   'De Yas positief of negatief symbool
    
   
Dim YaxisZeroRequest As Bit 

    Dim
ZaxisJobCounter As Word    
'Z axis job counter
    
ZaxisJobCounter = 0
    Dim ZaxisJobCounterNeg As Bit  
'Z axis if setpoint is negative
    
ZaxisJobCounterNeg = 0
    
  
    Dim ZaxisPosPulse As SDword 
'Effectieve positie van de as in pulsen (meest correcte plaatsbepaling)
   
Dim ZaxisPosP1 As SDword    'Positie1 zijn de milimeters op scherm
   
Dim ZaxisPosP2 As Dword    'Positie2 zijn de tienden van een milimeter op scherm
   
Dim ZaxisPosNeg As Byte   'De Zas positief of negatief symbool
   
   
Dim ZaxisZeroRequest As Bit
   
   
'Tijdelijk geheugen, gebruikt voor de 3-assen.
   
Dim Temp1SDword As SDword     ' Tijdelijk geheugen voor berekeningen.
   
Dim Temp2SDword As SDword     ' Tijdelijk geheugen voor berekeningen. 
   
Dim Temp3SDword As SDword     ' Tijdelijk geheugen om van Sign to non signed te gaan
  
    'Na opstart even stabiliseren.         
   
DelayMS 300
   
'Wis alles van het LCD scherm.
    
Cls
  
  
'Activeer de periodieke interrupt. 
   
T0CS = 0  'internal clock
   
PSA = 0   'Prescaler zit aan de TMR0
   
PS0 = 0
   
PS1 = 0
   
PS2 = 1
   
   
'prescaler setting
    'BIT    TMR0 
    '210B
    '000    1:2
    '001    1:4
    '010    1:8
    '011    1:16
    '100    1:32
    '101    1:64
    '110    1:128
    '111    1:256
   
   
   
On_Interrupt GoTo InterruptMGMT    
  
'Elke X miliseconden gaan we onze interrupt doen.


'In het hoofdprogramma kunnen "lange" vertragingen optreden, zoals het schrijven
'naar het LCD
'Het pulsen en bijhouden van de positie wordt in de interrupt blok gedaan.

Main:
   
GIE = 1    'Alle interrupts aan
   
T0IE = 1     'Enables interrrupt during counter TMR0 overflow
   
               
DelayUS 100
                DOMAIN  = 1  
                DelayUS 4
                DOMAIN = 0
   
              

''------------------------Begin van omrekening absolute positie in pulsen naar mm voor HMI'----------------------------------'   

'Berekening voor de Xas

                'Globale variabelen resetten:
                'Normaal worden deze steeds overschreven.
               
Temp1SDword = 0
                Temp2SDword = 0
                Temp3SDword = 0

'Eerst gaan we de counter (die signed is) delen door het aantal stappen van de stappenmotor
                'Alles achter de komma valt in Temp1 weg
                    
Temp1SDword =  XaxisPosPulse / 200
               
'Nadien delen door 2, wat eigenlijk neer komt op delen door 200, x100, dus
                'Idem als Temp1, maar met 100 groter om met int waarden achter de komma te kunnen rekenen            
                    
Temp2SDword =   XaxisPosPulse /2
               
'Als we het 100x grotere getal verminderen met alles voor de komma, blijft enkel nog de rest achter de komma over (zit in temp3)
                    
Temp3SDword =  Temp2SDword -(Temp1SDword * 100)   'achter de komma, op 2 honderdsten
                    
                     'conversie van sign to non sign
                'Aangezien beide met een sign werken, en we zelf continu de sign willen laten zien
                'gaan we hier over naar unsgined, dus als ABSOLUUT, voor getallekens op het LCD te laten zien.
                    
XaxisPosP1 = Abs(Temp1SDword)
                     XaxisPosP2 =  Abs(Temp3SDword)

         
'Nhier kijken we of een van de variabelen negatief is.
          'Indien ja, dan zetten we er een minneke voor
          
If Temp1SDword.15 = 1 Or Temp3SDword.15 = 1 Then
                 
XaxisPosNeg = 45
'een "-" symbool in bytevorm voor LCD
             
Else
              
XaxisPosNeg = 43
'een "+" symbool in bytevorm voor LCD
          
EndIf
          
          
'Berekening voor de Yas   

                'Globale variabelen resetten:
               
Temp1SDword = 0
                Temp2SDword = 0
                Temp3SDword = 0
       
          
'Eerst gaan we de counter (die signed is) delen door het aantal stappen van de stappenmotor
                'Alles achter de komma valt in Temp1 weg
                    
Temp1SDword =  YaxisPosPulse / 200
               
'Nadien delen door 2, wat eigenlijk neer komt op delen door 200, x100, dus
                'Idem als Temp1, maar met 100 groter om met int waarden achter de komma te kunnen rekenen            
                    
Temp2SDword =   YaxisPosPulse /2
               
'Als we het 100x grotere getal verminderen met alles voor de komma, blijft enkel nog de rest achter de komma over (zit in temp3)
                    
Temp3SDword =  Temp2SDword -(Temp1SDword*100)   'achter de komma, op 2 honderdsten
                    
                     'conversie van sign to non sign
                'Aangezien beide met een sign werken, en we zelf continu de sign willen laten zien
                'gaan we hier over naar unsgined, dus als ABSOLUUT, voor getallekens op het LCD te laten zien.
                    
YaxisPosP1 = Abs(Temp1SDword)
                     YaxisPosP2 =  Abs(Temp3SDword)

         
'Nhier kijken we of een van de variabelen negatief is.
          'Indien ja, dan zetten we er een minneke voor
          
If Temp1SDword.15 = 1 Or Temp3SDword.15 = 1 Then
                 
YaxisPosNeg = 45
'een "-" symbool in bytevorm voor LCD
             
Else
                 
YaxisPosNeg = 43
'een "+" symbool in bytevorm voor LCD
          
EndIf
          

 
'Berekening voor de Zas    
 
                'Globale variabelen resetten:
               
Temp1SDword = 0
                Temp2SDword = 0
                Temp3SDword = 0
                     
               
'Eerst gaan we de counter (die signed is) delen door het aantal stappen van de stappenmotor
                'Alles achter de komma valt in Temp1 weg
                    
Temp1SDword =  ZaxisPosPulse / 200
               
'Nadien delen door 2, wat eigenlijk neer komt op delen door 200, x100, dus
                'Idem als Temp1, maar met 100 groter om met int waarden achter de komma te kunnen rekenen            
                    
Temp2SDword =   ZaxisPosPulse /2
               
'Als we het 100x grotere getal verminderen met alles voor de komma, blijft enkel nog de rest achter de komma over (zit in temp3)
                    
Temp3SDword =  Temp2SDword -(Temp1SDword*100)   'achter de komma, op 2 honderdsten
                    
                     'conversie van sign to non sign
                'Aangezien beide met een sign werken, en we zelf continu de sign willen laten zien
                'gaan we hier over naar unsgined, dus als ABSOLUUT, voor getallekens op het LCD te laten zien.
                    
ZaxisPosP1 = Abs(Temp1SDword)
                     ZaxisPosP2 =  Abs(Temp3SDword)

         
'Nhier kijken we of een van de variabelen negatief is.
          'Indien ja, dan zetten we er een minneke voor
          
If Temp1SDword.15 = 1 Or Temp3SDword.15 = 1 Then
                 
ZaxisPosNeg = 45
'een "-" symbool in bytevorm voor LCD
             
Else
              
ZaxisPosNeg = 43
'een "+" symbool in bytevorm voor LCD
          
EndIf
         
''---------------------Einde van de omrekening van de absolute positie-------------------------------------------------------        
         
''-----------------------Alle actuele posties op het scherm laten zien.------------------------------------------------------               
         
Print At 1,1, "X-AS:",XaxisPosNeg, Dec3 XaxisPosP1, ",", Dec2 XaxisPosP2,"mm" ,"X", Dec4 XaxisJobCounter
      
          Print At 2,1,
"Y-AS:",YaxisPosNeg, Dec3 YaxisPosP1, ",", Dec2 YaxisPosP2,"mm" ,"Y"Dec4 YaxisJobCounter
      
          Print At 3,1,
"Z-AS:",ZaxisPosNeg, Dec3 ZaxisPosP1, ",", Dec2 ZaxisPosP2,"mm" ,"Z", Dec4  ZaxisJobCounter  
           
          Print At 4,1,
"FEEDR:", Dec2 VARFEEDRATE , ARROW , "STEP:" , Dec2 STEPSIZEARRAYP2[STEPSIZESELECTION] ,"," , Dec1 STEPSIZEARRAYP1[STEPSIZESELECTION], "mm"  
     
         
 
''----------------------------------ROTARY ENCODER PART-------------------------------------  

 
                          
            'Eerste detectie van de rotary encoder.
          
If ROTFIRST = 0  Then    'ROTFIRST doen in feite ook en positieve flank,
                                    'want ik onhou dat er eerste puls geweest is.      
               
If DIROT1 = 1 And DIROT2 = 0  Then
               
ROTFIRST  = 1
'rotary first is bij 0, uit, bij 1 DIROT1 en bij 2 DOROT2
                     
               
EndIf
               
                If
DIROT1 = 0 And DIROT2 = 1  Then
               
ROTFIRST  = 2
'rotary first is bij 0, uit, bij 1 DIROT1 en bij 2 DOROT2
              
               
EndIf
            
           EndIf
          
            
'Opmerking, bij de 2de flank gaan we effectief de varfeedrate of steprate aanpassen.
         
           'Tweede flank van rotary encoder
          
If ROTFIRST = 1 And DIROT2 = 1 And Pflank = 0 Then    'tweede flank gedetecteerd, tel 1 waarde bij. 
          
                        
If ROTSEL = 1 Then
                        
'Stepsize aanpassen
                               
If    STEPSIZESELECTION < 5 Then
                              
STEPSIZESELECTION =  STEPSIZESELECTION + 1
                                EndIf
                               
                         Else
                        
'Feedrate aanpassen                            
                                   
If  VARFEEDRATE < 15 Then '15
                                   
VARFEEDRATE = VARFEEDRATE + 1      
                                    EndIf
                
                         EndIf

           
Pflank = 1       
'set de flankbit om maar 1x bij te tellen, wordt gereset als beide inputs laag zijn. 
           
EndIf
          
           If
ROTFIRST = 2 And DIROT1 = 1  And Pflank2 = 0 Then
                           If
ROTSEL = 1 Then
                           
'Stepsize aanpassen
                               
If    STEPSIZESELECTION > 0 Then
                              
STEPSIZESELECTION =  STEPSIZESELECTION - 1
                                EndIf
                               
                         Else
                          
'Feedrate aanpassen                      
                                    
If VARFEEDRATE > 1 Then
                                     
VARFEEDRATE = VARFEEDRATE -1      
'tweede flank gedetecteerd, tel 1 waarde af.                                   
                                    
EndIf
                                    
                         EndIf
                      
           
Pflank2 = 1 
'set de flankbit om maar 1x bij te tellen, wordt gereset als beide inputs laag zijn.                
           
EndIf 
           
           
'Wanneer ROTFIRST ingesteld staat en beide ingangen zijn laag, reset dan de ROTFIRST en positive flanken.
           
If  ROTFIRST = 1 Or ROTFIRST = 2  Then     
                          If
DIROT2 = 0  And DIROT1 = 0 Then
                        
ROTFIRST = 0
'Reset detectie
                        
Pflank = 0
                         Pflank2 = 0
                         EndIf
            EndIf
           
 
'--------------------------Hier afhandeling van STEPSIZE-------------------------------
 
            'In array van 0 tot 5, predefined values
         
VARSTEPSIZE =   STEPSIZEARRAY [STEPSIZESELECTION]
   
 
'----------------------------Hier drukknop afhandeling van de rotary encoder knop----------------
 
            
         
Button DIROTPUSH,1,255,200,BTNVARRPUSH,0,SkipROTPUSH
          Toggle  ROTSEL      
SkipROTPUSH:

       
'Puur voor pijltje op LCD om aante duiden welke we kunnen instellen
       
If ROTSEL = 1 Then
       
ARROW = 199
        Else
       
ARROW = 200
        EndIf
     
         
'------------------------------END OF ROTARY ENCODER PART----------------------------------------      
                   
                      

' -----------------------------BEGIN OF SETPOINT BY PUSHBUTTONS------------------------------------   
    ' XaxisMove
    
     'X as positief verplaatsen door data in de jobcounter te steken
    
Button DIXADD,1,255,200,BTNVARXADD,0,SkipXADD
            
'We zijn nog bezig met onze job af te werken en er wordt in omgekeerde richting gedrukt.
            
If  XaxisJobCounter > 0 And  XaxisJobCounterNeg = 1 Then
              GoTo
SkipXADD 
'Doe niets
             
EndIf
    
            
XaxisJobCounterNeg = 0
             XaxisJobCounter    = XaxisJobCounter  + VARSTEPSIZE
SkipXADD:           
        
           
    Button DIXSUB,1,255,200,BTNVARXSUB,0,SkipXSUB
           
'We zijn nog bezig met onze job af te werken en er wordt in omgekeerde richting gedrukt.
            
If  XaxisJobCounter > 0 And  XaxisJobCounterNeg = 0 Then
              GoTo
SkipXSUB 
'Doe niets
             
EndIf
             
            
XaxisJobCounterNeg = 1
             XaxisJobCounter    = XaxisJobCounter  + VARSTEPSIZE
SkipXSUB: 

           
'Zet bit hoog om tijdens interrupt routine de telling op nul te zetten
           
Button DIXZERO,1,255,200,BTNVARXZERO,0,SkipXZERO
            XaxisZeroRequest = 1
         
SkipXZERO:
'''''''''''''''''''''''''''
  ' YaxisMove
    
     'Y as positief verplaatsen door data in de jobcounter te steken
    
Button DIYADD,1,255,200,BTNVARYADD,0,SkipYADD
           
'We zijn nog bezig met onze job af te werken en er wordt in omgekeerde richting gedrukt.
            
If  YaxisJobCounter > 0 And  YaxisJobCounterNeg = 1 Then
              GoTo
SkipYADD 
'Doe niets
             
EndIf
             
            
YaxisJobCounterNeg = 0
             YaxisJobCounter    = YaxisJobCounter  + VARSTEPSIZE
SkipYADD:           
        
           
    Button DIYSUB,1,255,200,BTNVARYSUB,0,SkipYSUB
           
'We zijn nog bezig met onze job af te werken en er wordt in omgekeerde richting gedrukt.
            
If  YaxisJobCounter > 0 And  YaxisJobCounterNeg = 0 Then
              GoTo
SkipYSUB 
'Doe niets
             
EndIf

            
YaxisJobCounterNeg = 1
             YaxisJobCounter    = YaxisJobCounter  + VARSTEPSIZE
SkipYSUB:



             Button DIYZERO,1,255,200,BTNVARYZERO,0,SkipYZERO
            YaxisZeroRequest = 1
         
SkipYZERO:
''''''''''''''''''''''''''
' ZaxisMove
    
     'Z as positief verplaatsen door data in de jobcounter te steken
    
Button DIZADD,1,255,200,BTNVARZADD,0,SkipZADD
            
'We zijn nog bezig met onze job af te werken en er wordt in omgekeerde richting gedrukt.
            
If  ZaxisJobCounter > 0 And  ZaxisJobCounterNeg = 1 Then
              GoTo
SkipZADD 
'Doe niets
             
EndIf
             
            
ZaxisJobCounterNeg = 0
             ZaxisJobCounter    = ZaxisJobCounter  + VARSTEPSIZE
SkipZADD:           
        
           
    Button DIZSUB,1,255,200,BTNVARZSUB,0,SkipZSUB
                
'We zijn nog bezig met onze job af te werken en er wordt in omgekeerde richting gedrukt.
            
If  ZaxisJobCounter > 0 And  ZaxisJobCounterNeg = 0 Then
              GoTo
SkipZSUB 
'Doe niets
             
EndIf
             
            
ZaxisJobCounterNeg = 1
             ZaxisJobCounter    = ZaxisJobCounter  + VARSTEPSIZE
SkipZSUB:

Button DIZZERO,1,255,200,BTNVARZZERO,0,SkipZZERO
            ZaxisZeroRequest = 1
         
SkipZZERO:

'''Einde van gewone drukknop acties.

                                
        
GoTo Main
   
'------------------------------END OF SETPOINT BY PUSHBUTTONS----------------------------------------          
   
'------------------------------INTERRUPT PART-------------------------------------------------------     
InterruptMGMT:
  Context Save
 
 
'HERE SYNCRONIOUS PROGRAM EXECUTION
  
   'Hier moeten we volgende taken afhandelen:
   '*Afhandelen van axis zero requests, enkel wanneer die specifieke as geen lopende "job" heeft
   '*Afhandelen van noodstop -> DISTOP
   '*Afhandelen van jobcounterwaarden, om steppenmotoren aan te sturen.
  
    ''Debugfeature, uitgang om via scope te kunnen zien hoe snel de interrupts komen
   
DOINT  = 1  
    DelayUS 4
    DOINT = 0
    
''----Einde debug feature-----------
      
     ''Emergency stop all
     ''Opgelet! bij gebruik van de noodstop loopt de indicatie niet meer 100% meer gelijk met de pulsen die gegeven zijn.
     'Je kan dus op een willekeurige positie gestopt zijn.
     'Je doen 200stappen per mm, dus op 0.005mm nauwkeurig in theorie
     'We laten maar stappen toe van 0.1mm, dus tussen 0.1 en 0 kunnen we na een noodstop vallen.
     'Opnieuw assen "nullen" is de meest nauwkeurige manier om opnieuw te beginnen.
    
    
If DISTOP = 1 Then
      
XaxisJobCounter = 0
       YaxisJobCounter =0
       ZaxisJobCounter =0
     EndIf
      
      
         
''---------------------Xas sturing-----------------------------------          
             'Enkel uitvoeren als timer verlopen is
           
If FEEDRATECOUNTER <= 0 Then
           
               
'Er is een "job", we staan niet op 0
               
If XaxisJobCounter > 0 Then
               
                               
'Check in welke richting we moeten werken
                               
If XaxisJobCounterNeg = 1 Then
                               
'negtive sequence
                               
DOXDIR = 1
                                    XaxisJobCounter = XaxisJobCounter - 1
                                   
                                   
'Update van de positie voor visualisatie
                                   
XaxisPosPulse =   XaxisPosPulse - 1
                                Else
                               
'positive sequence
                                 
DOXDIR = 0
                                   XaxisJobCounter = XaxisJobCounter - 1  
                                  
                                   
'Update van de positie voor visualisatie
                                   
XaxisPosPulse =   XaxisPosPulse + 1
                                EndIf
                   
                   
                 
'One pluse
                   
DOXPULSE = 1
                   
                    DelayUS 20
                    DOXPULSE = 0
                   
                   
                    Else
                   
'Geen "job" bezig, dus mogen we onze teller nullen, indien gewenst
                    'Opgelet, adhv de feedrate kan het zijn dat we deze routine langszaam doorlopen, dus misschien in interrupt routine
                    'apart plaatsen.
                    
If XaxisZeroRequest = 1 Then
                    
XaxisPosPulse = 0  
'reset telling
                    
XaxisZeroRequest = 0 'reset bit
                    
EndIf
                   
                    EndIf
               
              EndIf 
'''----------------------------------------------------------------------        .
  ''---------------------Yas sturing-----------------------------------          
             'Enkel uitvoeren als timer verlopen is
           
If FEEDRATECOUNTER <= 0 Then
           
                       
'Er is een "job", we staan niet op 0
                       
If YaxisJobCounter > 0 Then
                       
                                       
'Check in welke richting we moeten werken
                                       
If YaxisJobCounterNeg = 1 Then
                                       
'negtive sequence
                                       
DOYDIR = 1
                                            YaxisJobCounter = YaxisJobCounter - 1
                                           
                                           
'Update van de positie voor visualisatie
                                           
YaxisPosPulse =   YaxisPosPulse - 1
                                        Else
                                       
'positive sequence
                                         
DOYDIR = 0
                                           YaxisJobCounter = YaxisJobCounter - 1  
                                          
                                           
'Update van de positie voor visualisatie
                                           
YaxisPosPulse =   YaxisPosPulse + 1
                                        EndIf
                           
                           
                         
'One pluse
                           
DOYPULSE = 1
                           
                            DelayUS 20
                            DOYPULSE = 0
                           
                           
                            Else
                                   
'Geen "job" bezig, dus mogen we onze teller nullen, indien gewenst
                                    'Opgelet, adhv de feedrate kan het zijn dat we deze routine langszaam doorlopen, dus misschien in interrupt routine
                                    'apart plaatsen.
                                    
If YaxisZeroRequest = 1 Then
                                    
YaxisPosPulse = 0  
'reset telling
                                    
YaxisZeroRequest = 0 'reset bit
                                    
EndIf
                                   
                            EndIf
                       
                 EndIf
'''----------------------------------------------------------------------      

  ''---------------------Zas sturing-----------------------------------          
             'Enkel uitvoeren als timer verlopen is
           
If FEEDRATECOUNTER <= 0 Then
           
                       
'Er is een "job", we staan niet op 0
                       
If ZaxisJobCounter > 0 Then
                       
                                       
'Check in welke richting we moeten werken
                                       
If ZaxisJobCounterNeg = 1 Then
                                       
'negtive sequence
                                       
DOZDIR = 1
                                            ZaxisJobCounter = ZaxisJobCounter - 1
                                           
                                           
'Update van de positie voor visualisatie
                                           
ZaxisPosPulse =   ZaxisPosPulse - 1
                                        Else
                                       
'positive sequence
                                         
DOZDIR = 0
                                           ZaxisJobCounter = ZaxisJobCounter - 1  
                                          
                                           
'Update van de positie voor visualisatie
                                           
ZaxisPosPulse =   ZaxisPosPulse + 1
                                        EndIf
                           
                           
                         
'One pluse
                           
DOZPULSE = 1
                           
                            DelayUS 20
                            DOZPULSE = 0
                           
                           
                            Else
                           
'Geen "job" bezig, dus mogen we onze teller nullen, indien gewenst
                            'Opgelet, adhv de feedrate kan het zijn dat we deze routine langszaam doorlopen, dus misschien in interrupt routine
                            'apart plaatsen.
                                    
If ZaxisZeroRequest = 1 Then
                                    
ZaxisPosPulse = 0  
'reset telling
                                    
ZaxisZeroRequest = 0 'reset bit
                                    
EndIf
                           
                            EndIf
                EndIf
''---------------------------------------------------------------------------------------- 

'''----------------------------------------------------------------------      
              'Opgelet, volgende code moet onder de assensturing komen
              'Dit omdat op de "0" positie de acties worden gedaan
              'Nadien mag de teller terug gereset worden volgens feedrate
       
              'Hier de VARFEEDRATE berekening
              'De VARFEEDRATE gaat van 1 tot 100
              'We gaan de macht van 2 erop toepassen om lineair op te lopen in tijd.
              'Aangezien we geen machtsfunctie hebben, doen we heel eenvoudig feedrate vermenigvuldigd met nofmaals de feedrate 
             
             
If  FEEDRATECOUNTER = 0 Then         
             
VARFEEDRATEPOW2 = VARFEEDRATE * VARFEEDRATE     
              FEEDRATECOUNTER = VARFEEDRATEPOW2
              EndIf
'''------------------------------------------------------------------------- 
      
       'Hier bij elke interrupt de feedratecounter verminderen met 1
      
      
FEEDRATECOUNTER  = FEEDRATECOUNTER - 1 
     
''------------------------------------------------------------------------ 

             

'Reset interrupt vlag en ga terug naar main programma
        
T0IF = 0
  Context Restore
Return
      
    
    



Everything on the breadboard.
Here the source code:
Download schematic file.