Gallery, Projects and General > Project Logs
X2 X-axis Stepper motor Power Feed - (possible CNC conversion?)
<< < (13/19) > >>
No1_sonuk:
Remember you have a limited number of stack levels.  A hardware interrupt will use one of those, so you have to ensure that you don't use more than the total available minus 1 for the main loop and the interrupt routine combined.  So if you have the normal 8 levels available, don't use more than 7 total for the main loop and the interrupt service routine.

EDIT:-
BTW, the "messy" C instructions is one reason why I'd probably code at least some of this sort of thing in Assembler.  That guarantees the timing is as accurate as the processor can make it.  That is, however, a personal choice, and due mainly to the fact that I've programmed PICs almost exclusively in Assembler for several years.
raynerd:
I`ve got a bit stuck again with this. I have a blurb at the start.

My issue now is that if I want to reset a limit past the previous limit, I can`t get there!! I need to ignore limits while in "limit setting mode" or in terms of the code, while (memory).  I could do that by setting something like;


--- Quote ---while (memory)
{
 mode = 1,
Rest of limit setting code....
}

--- End quote ---

and then in the interupt pulse section


--- Quote ---while (!mode)        // while not in mode
{
rest of code checking limits // check limits then move onto pulse
}
pulse.       // if we are in mode, it will just pulse and not check limits.

--- End quote ---

However now my issue is that if I did something like the above code, I need to use left and right to jog the motor to position while ignoring the limits. I then need to set limits. So how do I set limits as I am now using the left right to jog. Does this make sense. I could add another button that removed limits at any point but ideally I wanted to keep it simple by using just the memory button and left right to set limits. Maybe the design of this is not possible. Any thoughts...

updated code below:

--- Quote ---/* X-axis Stepper Controller
The controllers primary functions are to produce a pulse train with a
step pulse of approximately 1 microsecond delay to the "step" pin and define
the "dircection" pin  1/0 to set the motor direction. Limits can be set in both
directions.

Functions:
left and right jog the motor until limit is reached.
To set limits, jog to tableposition of required limit. Hold memory button while
pressing the left or right  to set the corresponding limit. If memoryLED lights,
error and may need correcting - limitLeft >= limitRight

Development:
1.Variable Speed Control via ADC.
2.Rapid Return - pressing (new) button while holding left or right sets max speed
until limit is reached.
3.Limit to Limit - jogs motor between limits continually.
4.Limit to Limit; rapid return - as above but user sets one direction at top speed

Code Development:
1.Ensure that only one button is pressed at a time
2.In cases where the motor is stepping in one direction and the opposite button
is pressed, treat as a stop and require two presses to reverse direction
*/

// define which pins our buttons are on
#define right PORTC.b0
#define left PORTC.b1
#define stop PORTC.b2
#define memory PORTC.b3

// define which pins our motor is connected to
#define memoryLed PORTC.b4
#define motorLed PORTC.b5
#define step PORTC.b6
#define direction PORTC.b7

// LCD display config.
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections


long tablePos = 0;
long limitLeft = -100000;
long limitRight = 100000;
int motorRun = 0;

void interupt()    // step motor interupt - Only steps if motorRun is set.
{
    TMR0IF_bit = 0;    // clear TMR0IF
    TMR0L  = 96;       // reset counter

    if (motorRun)      // interupt only steps motor if motorRun is set in main.
    {

    // if going right then check right limit - if greater than limit, motorRun = 0, stops motor.
        if (direction)
        {
            if (tablePos >= limitRight)
            {
                motorRun = 0;
                return;
            }
        }
        else
        {
            if (tablePos <= limitLeft)
            {
                motorRun = 0;
                return;
            }
            }

    // these 3 lines step the motor
    step = 1;       // set the step line high
    delay_us(1);    // wait 1 micro second
    step = 0;       // and low again - the motor will now move one step
      // update the table position
    if (direction)
        tablePos++;
    else
        tablePos--;
    }
 }
 
//===========================================
// when the PIC is first switched on it will start to run at "main"

void main()
{
    char motorSpeed = 3;    // 3 = fast, 255 = slow
    char count;             // misc use
    int adc;                // somewhere to put the ADC we read

    // Set TMR0 in 8bit mode, assign prescaler to TMR0
    T0CON  = 0xC4;

    // set ADC's
    ADCON0 = 1;         // enable ADC
    ADCON1 = 0b1110;    // enable ADC only for ADC 0

    // set all the pins on PORT C to 'off' before we start
    PORTC = 0;

    // set the tri-state buffer. Pins set to '1' are input, '0' are output
    // we've done this in binary to make it easier to see
    // each number is 1 pin, right hand is pin 0, left is pin 7
    TRISC = 0b00001111;
    TRISB = 0;
    TRISA = 0b11111111;

    while(1)
    {
    //Sets interupt - triggers into step interupt but if motorRun is not set, motor does not run.
    TMR0L  = 96;         // Timer0 initial value
    INTCON = 0xA0;       // Enable TMRO interrupt

        // Checks left and right buttons - sets direction and motorRun
        if (left)
        {
            direction = 0;
            motorRun = 1;
        }
        if (right)
        {
            direction = 1;
            motorRun = 1;
        }
        // Stop button
        if (stop)
        motorRun = 0; // stop the motor

        // -- ----------------Limit Setting ------------------------
        // -- hold down memory and press left or right to set limit.
        // ---------------------------------------------------------
        while (memory)        // loops here while waiting for limit to be set.
        {
                // set limit left or right
                if (left)
                    limitLeft = tablePos;
                if (right)
                    limitRight = tablePos;
                   
                // wait for left/right to be released
                while (left || right);
        }
       
        // Checks limitLeft is not >= to limitRight
        //  memeryLed = 1 indicated error to user
        if (limitLeft >= limitRight)
        memoryLed = 1;      // COULD I ALSO DO SOMETHING ELSE HERE? maybe reset limit after a delay?
        else
        memoryLed = 0;

        //------------------------------
        // step the motor
        if (motorRun)   // are we moving the motor?
        {
            motorLed = 1;

            /* OLD ADC SPEED CONTROL NOT IN USE
            read the ADC and set the speed (delay)
            adc = 512;                   // MyADC needs replacing with  ADC_Read(0);
            adc = adc >> 2;         // divide by 4
            if (adc < 3)
                adc = 3;
            for(count = 0; count < 10; count++)
            Delay_Cyc(adc); */
        }
        else
            motorLed = 0;
        }
}

--- End quote ---
kvom:
You could do limit resetting by memory-stop sequence.  Using the automaton model each button press is a 2-part state.  When you detect a press you enter a state waiting for a release, at which point you enter the state signalled by that button.  Here's some pseudo code:

  switch (state)
  {
     case stop:
       if (memory)  // memory button pressed
       {
          state = memory1;
          break;
        }

      case memory1:
        if (!memory)  // button released
        {
          state = memory2;
          break;
        }

      case memory2:
        // turn on LED if not already on
        // check for next keypress: memory, left, right, stop
        break;

    }
No1_sonuk:
WRT setting limits:
You could do it so that you hold the memory button and both jog buttons together (like the MS CTRL-ALT-DEL combination) to disable the limits, then do it again to enable the limits after setting them as you already have set up.
If you don't reset the limit numbers when they're disabled, that also gives you the option to temporarily disable the limits at any time.

Having said that, a separate switch for limit enable/disable would make the code FAR simpler.  Even easier if it's a toggle switch.  Using a toggle switch would mean you'd only need to check the state of the switch when one of the limits is reached, rather than having to continuously monitor a pushbutton and store the result in a flag variable.  It also gives a physical indication of its status.

WRT this:

--- Quote ---4.Limit to Limit; rapid return - as above but user sets one direction at top speed
--- End quote ---
Could be a bad idea if you're cutting - backlash, tool flex, etc. could mean you would cut on the way back.  On a lathe, that might make a shiny-smooth surface going one way, only to cut a shallow "thread" on the way back!  If it stopped and waited for the user to press a button, that'd give the option to move the work or cutter before the rapid traverse.
raynerd:
A bit of an update. I`ve been doing some updates to my mill at the moment but I`m hoping I should have some time over the next week to get a first simple prototype built. Quite a bit to do yet.



Navigation
Message Index
Next page
Previous page

Go to full version