Gallery, Projects and General > Project Logs |
X2 X-axis Stepper motor Power Feed - (possible CNC conversion?) |
<< < (11/19) > >> |
kvom:
--- Quote ---My issue is that I have used a lot of messy delay code in my "void CupDisplay" function. Anyone know a better way to do it? --- End quote --- I recoded your program to make it a bit less "messy"; Hope this helps. Unfortunately the website messes up the formatting a bit. --- Quote ---// define which pins our buttons are on #define button1 PORTA.b0 #define button2 PORTA.b1 #define button3 PORTA.b2 #define YourLED1 PORTB.b0 #define YourLED2 PORTB.b1 #define YourLED3 PORTB.b2 // 3 buttons 1,2,3 linked to YourLED1, YourLED2, YourLED3 // When button is pressed corresponding LED lights and computer counts CupLED1-3 // CupLED1-3 lights. // if YourLED = CupLED you win - flashing. Game Resets // else...you loose. Game Resets char buttonPressed; // a variable that saves our button press char cup; char LED[4] = {0b00000000, 0b00000001, 0b00000010, 0b00000100}; char portvals[10] = {1,2,4,2,1,2,4,2,1,2}; int delays[10] = {300,300,400,400,400,500,500,500,650,750}; void cupDisplay () { for (int i=0; i<10; i++) { PORTC = portvals; delay_ms = delays; } PORTC = LED[cup]; delay_ms(1000); if (buttonPressed == cup) { for (int i=0; i<4; i++) { PORTB = PORTC = 7; delay_ms(250); PORTB = PORTC = 0; delay_ms(250); } } else { PORTB = PORTC = 7; delay_ms(2000); } } char ReadButtons () { if (button1) return 1; if (button2) return 2; if (button3) return 3; return 0; } void main() { int adc; // somewhere to put the ADC we read // PIC's have lots of hardware - in this case in order to use PORTB // we have to turn off the ADC's // All ports digital ADCON1 = 0x0F; CMCON = 0x07; // set all the pins on PORT B to 'off' before we start PORTA = PORTB = 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 TRISA = 0b11111111; TRISB = 0b00000000; TRISC = 0b00000000; // ============= Code Proper Starts ======== while (1) // loop forever { while ((buttonPressed = ReadButtons()) == 0); cup = 1; while (ReadButtons() > 0) // counts while buttons are pressed { cup++; if (cup > 3) cup = 1; } switch (buttonPressed} { case 1: YourLED1 = 1; break; case 2: YourLED2= 1; break; case 3: YourLED3= 1; } cupDisplay (); PORTA = PORTB = PORTC = 0; } } --- End quote --- |
raynerd:
Thanks for your suggestions, I have the speed running off a variable resistor/pot so it is basically just a twist knob to alter the speed at any point. I like the idea of auto traverse with one button press from one side to the other and then perhaps wait for a button pressed for the return. I doubt without a multi axis cnc you would wish for it to traverse from one side to the other continuously? Maybe - and I bet it would be easy to code in the function. Also, regarding Tims suggestion of rapid traverse, I could include a button which sets an auto fast speed with a one press it returns it back to the other limit and then auto knocks off, returning back to the variable speed set by the pot for the cut. Any more suggestions welcome! Kvom - I really appreciate the time taken for you to run through my code. I have actually done some bits of it already myself. I had removed the duplicated "if" statements at the bottom of my code and replaced it with the "switch" statement as you have. I also managed to have a go at a loop for the delay and display sequence. I knew I should be using the for statement and have seen through googling that the use of i for a variable is common for a count. I couldn`t get it to work properly with the delays because I hadn`t put them in a delay array as you have. I totally see now why it was not working and your corrections have really helped me understand how I should have done that, thanks! Could you or anyone else explain to me or better still show me how I could change the following code for my x-axis controller so that the actual motor stepping sequence will be carried out on an interrupt? At the present time, the motor stepping sequence ("stepMotor") is a global function and as such the PIC is not scanning anything else while carrying out this function. I believe if I put the stepMotor sequence as an interupt, it will both allow the controller unit to be functional (i.e to scan for other user input operations, stop, or "do something else!") while the motor is running and also, I believe interupts are a better timing sequence and will allow sharper control of the pulse timing. I am not to sure, therefore, if the motorStep sequence is moved to an interupt whether the use of a delay as a speed control will be changed?? Or something to do with the interupt itself being used for timing. I`m all a bit muddled up... Chris --- Quote ---// Function: // Press 'mem', light comes on. // Move left & right until at position. // Press 'mem' light starts to flash. // Press left or right to set that limit, light goes out and unit works as before. // SHOULD THE MEMORY SETTING BE CHANGED TO WORK THE FOLLOWING????? //A button that toggles free move or limited. //at any point in either mode you can simply press the 'memory' button followed //by left or right to set the limit. // 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 = -10000; long limitRight = 10000; int motorRun = 0; // mode == 0 : running // mode == 1 : setting limits char mode = 0; //=========================================== // this function moves the motor 1 step // only moving if it can and also updates the table position void stepMotor() { if (!mode) // we only take note of the limits in mode 0 (otherwise we're setting them) { // 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 ADC's ADCON0 = 1; // enable ADC ADCON1 = 0b1110; // enable ADC only for ADC 0 // set all the pins on PORT B 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) { if (left) // is left button pressed? { // if we get in here button must be pressed direction = 0; //set direction to 0 motorRun = 1; // start the motor } //------------------------------ // check for right button if (right) // right button pressed { direction = 1; // set direction to 1 motorRun = 1; // start the motor } //------------------------------ // check for stopping the motor if (stop) // stop button pressed motorRun = 0; // stop the motor //------------------------------ // handle setting the limits. //------------------------------ // is memory button pressed? if (memory) { // wait for it to be released while (memory); // if in 'run' mode, change to 'limit set' mode if (!mode) mode = 1; else { // in limit set mode - wait for left or right to be pressed while (!left && !right) // if neither are pressed then stay here { // be clever here and flash the memory light to show we're waiting delay_ms(2); count++; // count is 8 bits (char) - when it gets to 255, the next time it increments it goes to zero if (count > 128) // 5ms * 128 is a bit over 1/4 seconds - so light should flash about 2hz memoryLed = 0; else memoryLed = 1; } // depending on which button was pressed set the appropriate limit if (left) limitLeft = tablePos; if (right) limitRight = tablePos; // wait for left/right to be released and then we're done while (left || right); // we're finished so go back to 'run' mode mode = 0; } } //------------------------------ // if in 'limit set' mode then light the memory LED if (mode == 1) memoryLed = 1; else memoryLed = 0; //------------------------------ // step the motor if (motorRun) // are we moving the motor? { motorLed = 1; stepMotor(); // read the ADC and set the speed (delay) adc = 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 --- |
spuddevans:
--- Quote from: craynerd on January 09, 2010, 01:04:45 PM --- I could include a button which sets an auto fast speed with a one press it returns it back to the other limit and then auto knocks off, returning back to the variable speed set by the pot for the cut. --- End quote --- Why not code it so that the fast-traverse-button activates the fast traverse until a direction button is pressed and then released, ie you press the fast traverse button, press and hold the relevent direction button, then when the button is released then fast traverse function automatically is cancelled, returning the speed to the previously set speed via the pot. You could code it along the lines of the fast traverse button sets a flag to "1" and then the direction button could test that flag to see if it is set, if it is then it would traverse at the high speed, and then when the direction button is released it would clear the flag thereby cancelling the fast traverse. Tim |
BobWarfield:
That's the beauty of it being a computer: you can make it do anything. I imagine it is not all that much more costly than a regular power feed, yet it has the potential to be a lot more powerful. Just by changing software and adding a few switches you can provide a variety of functions: - Fast jog - Slow jog with potentiometer to control speed - Speed readout in IPM so you can adjust to match a recommended feed. Turn the potentiometer until you get the number - Or, provide a keypad to enter a feedrate - Push a button to set a stop. Now the stepper will always stop after that many step pulses and you have effectively got a software stop on your feed - Interface a handwheel-style pulse generator - Simple DRO function. Push a button to zero, and then the readout will tell you how far you've moved. The list goes on and on. It would not be hard to add a couple of circuits so that you can take the step/dir right out of a Mach3 breakout board. Now you have the ability to either run the g-code via Mach or run as a manual with power feeds. I've said for a long time the cost of fitting CNC is about the cost of power feeds and a nice DRO. Cheers, BW |
raynerd:
Tim, excellent idea. In C it will be even easier than that: if (left) { if (fastTraverse) motorSpeed = **TopSpeed; else motorSpeed = **ACD_PotSpeed Rest of move code..... } OK - over simplified but it won`t be far off. Bob - your totally right and thanks for the nice ideas. Regards Chris Chris |
Navigation |
Message Index |
Next page |
Previous page |