SirZusa 34 Posted October 31, 2011 Share Posted October 31, 2011 For my new project (a self made cnc-milling-machine - mostly for pcb-prototyping and some kind of soft woods or plastics) i need to control 3 stepper motors - i already built up the translator and power-part of (L297 + L298) first i tried interrupts - 30 kHz ... more than expected - but too less for my next project Benchmarking... maximum possible frequency is about 1.5 MHz on P1.3 ... so my 3 instructions (asm-equivalent: bitc, bits, jmp) take about 10 cycles? o.O this is really much ... for(; { // X-Axis P1OUT |= BIT3; P1OUT &= ~BIT3; } Benchmarking in a real configuration... ~ 119 kHz output on P1.3 - P1.5 for(; { // X-Axis BaseClockX--; if (BaseClockX == 0) { BaseClockX = mod_X; if (position_X != target_X) { P1OUT |= BIT3; P1OUT &= ~BIT3; if (dir_X == CW) { position_X++; } else { position_X--; } } } // 2 more axis with this setup i can realise following output-frequencys and speeds: Frequency IN Counter Frequency OUT s-1 mm / min 119000 1 119000 595 35700 119000 2 59500 297 17850 119000 3 39666 198 11900 119000 4 29750 148 8925 119000 5 23800 119 7140 119000 6 19833 99 5950 119000 7 17000 85 5100 119000 8 14875 74 4462 119000 9 13222 66 3966 119000 10 11900 59 3570 119000 11 10818 54 3245 119000 12 9916 49 2975 ... (i didnt want to copy the complete excel list in here) As you can see the accuracy gets better the higher the mod-value gets. My question: Is there any other possibility to create 3 independent output-frequencies? (I need a range from 0 - ~2500 Hz) --- Another option maybe to fix the frequency for all 3 axis to the same value and then just do the movement by pulsing the clock-inputs as needed. --- Has anyone of you tried to built up his own CNC-mill? Quote Link to post Share on other sites
oPossum 1,083 Posted October 31, 2011 Share Posted October 31, 2011 Here is some code that uses NCOs to generate three frequencies with 100 uHz (0.0001 Hz) resolution for a specified duration. There will be some jitter when 100000 / Frequency is not an integer. This may or may not be a problem. There are ways to reduce the jitter, but more hardware is required. Be very careful with the ISR code - it must be able to run in under 120 cycles. #include "msp430g2553.h" static long int timer = 0; // Duration of motion static long int pix = 0; // Phase increment static long int piy = 0; static long int piz = 0; static long int px = 0; // Position static long int py = 0; static long int pz = 0; static long int dx = 1; // Direction static long int dy = 1; static long int dz = 1; // Sample rate * (1 / resolution in Hz) static const long int pl = 1000000000; void set_fx(long int f) { pix = f - pl; } void set_fy(long int f) { piy = f - pl; } void set_fz(long int f) { piz = f - pl; } void main(void) { WDTCTL = WDTPW | WDTHOLD; // Disable watchdog DCOCTL = 0; BCSCTL1 = CALBC1_16MHZ; // Set DCO to 16 MHz DCOCTL = CALDCO_16MHZ; // P1DIR = 0x13; // I/O assignment P1REN = 0x00; // P1OUT = 0x02; // P1SEL = 0x10; // Enable SMCLK output P2DIR = 0x07; // P2REN = 0x00; // P2OUT = 0x00; // P2SEL = 0xC0; // TA0CTL = TASSEL_2 | MC_1; // Timer A config: SMCLK, count up TA0CCR0 = 160 - 1; // Setup Timer A CCR0 period for 100,000 Hz TA0CCTL0 |= CCIE; // Enable PWM interrupt _EINT(); // Enable interrupts set_fx(10000000); // 1000.0000 Hz set_fy(20000000); // 2000.0000 Hz set_fz(25000000); // 2500.0000 Hz timer = -1; // Run for a long time for(;; } #pragma vector = TIMER0_A0_VECTOR __interrupt void timer_a_isr(void) { static long int pax = 0; // Phase accumulator static long int pay = 0; static long int paz = 0; if(timer) { --timer; pax += pix; if(pax < 0) pax += pl; else { P2OUT |= 1; px += dx; P2OUT &= ~1; } pay += piy; if(pay < 0) pay += pl; else { P2OUT |= 2; py += dy; P2OUT &= ~2; } paz += piz; if(paz < 0) paz += pl; else { P2OUT |= 4; pz += dz; P2OUT &= ~4; } } } timotet, bluehash, SirZusa and 1 other 4 Quote Link to post Share on other sites
PentiumPC 119 Posted October 31, 2011 Share Posted October 31, 2011 How is the G-code translated? Quote Link to post Share on other sites
SirZusa 34 Posted October 31, 2011 Author Share Posted October 31, 2011 thanks oPossum - i will have a look on your code - 120 cycles sounds more than it is i will use the PC to translate and interpolate the g-code (especially 3-dimensional-arc-interpolations will take too long on MCU without lookup-tables) - the MCU will then get some data like speed (frequency) - target-position - sync (wait for all 3 axis reaching their target - should not be needed if everything works fine) Quote Link to post Share on other sites
PentiumPC 119 Posted October 31, 2011 Share Posted October 31, 2011 Just a suggestion, can you use 1 mcu for each channel? Quote Link to post Share on other sites
SirZusa 34 Posted October 31, 2011 Author Share Posted October 31, 2011 of course i can - i already thought about another architecture - 1 MCU like the 2553 for interaction with the pc - and 3x 2211 or some kind of the smaller ones for controlling the steppers Quote Link to post Share on other sites
zeke 693 Posted October 31, 2011 Share Posted October 31, 2011 I've read in the Ti datasheets that the max input frequency on an IO pin is something like 20MHz. What about cranking the MCU speed up to the max? Or have you done that already? Quote Link to post Share on other sites
nobody 47 Posted October 31, 2011 Share Posted October 31, 2011 You think about use MSP with high resolution timer ( "Timer_D" )? This timer work at frequency 16 x higher than processor clock frequency (256MHz at 16 MHz clock!!!) and give you more precision at frequency control. Look at [tipdf]slau208[/tipdf], chapter 16.1 (page 400) for more information. Quote Link to post Share on other sites
SirZusa 34 Posted October 31, 2011 Author Share Posted October 31, 2011 I've read in the Ti datasheets that the max input frequency on an IO pin is something like 20MHz. What about cranking the MCU speed up to the max? Or have you done that already? i think 16 MHz should be enough the steppers can only go up to about 3000 Hz (steps per second) - so there is no need for higher speed of the IO You think about use MSP with high resolution timer ( "Timer_D" )?This timer work at frequency 16 x higher than processor clock frequency (256MHz at 16 MHz clock!!!) and give you more precision at frequency control. Look at slau208, chapter 16.1 (page 400) for more information. i'm using the MSP430G2553 - i dont think that it has sich a timer --- with the help of oPossums piece of code i created the following function - works nice for now ... more to come in a separate thread with the complete code and more details on the configuration void set_Position_AbsoluteSpeed(unsigned long int x, unsigned long int y, unsigned long int z, unsigned long int absolute_speed) { // set new target position target_x = x; target_y = y; target_z = z; // calculate difference between actual position and target position static signed long int diff_x; static signed long int diff_y; static signed long int diff_z; static double diff_abs; diff_x = target_x - position_x; diff_y = target_y - position_y; diff_z = target_z - position_z; // determine directions and set them if (diff_x < 0) { ccw_x(); } else { cw_x(); } if (diff_y < 0) { ccw_y(); } else { cw_y(); } if (diff_z < 0) { ccw_z(); } else { cw_z(); } // calculate absolute difference between the 2 points diff_abs = sqrt(diff_x * diff_x + diff_y * diff_y + diff_z * diff_z); // calculate the speeds for each axis set_frequency_x(absolute_speed / diff_abs * diff_x); set_frequency_y(absolute_speed / diff_abs * diff_y); set_frequency_z(absolute_speed / diff_abs * diff_z); // calculate movement time double time = diff_abs * pl / absolute_speed; // and set the time set_duration(time); } i have little problems with the sqrt ... it returns wrong values when the inner value gets too big ... i will modify the code a bit more - the time-driven motion makes trouble when hitting the endpoints - sometimes steps get lost ... so i will change it to an event-driven "endpoint-detection" Quote Link to post Share on other sites
oPossum 1,083 Posted October 31, 2011 Share Posted October 31, 2011 You should do this calculation on the PC using double floating point. That will fix the overflow and precision problems. The time based motion should move all the axis very close to the desired target stop position if the frequency and time calculations are all correct. The endpoint determined by the MCU should be used as the next start point by the PC to keep cumulative error under control. The advantage of a time based limit is that it keeps the ISR fast and the code simple (one time limit check instead of 3 position limit check). Quote Link to post Share on other sites
nobody 47 Posted October 31, 2011 Share Posted October 31, 2011 You need to use endpoint ramps into stepper controll algoritmus (smooth change stepping frequency up / down at the begin / end of line to controll acceleration). And high resolution timers help you use higher levels of accuracy - using microstepping. You will be able using for example 30000 microsteps instead of 3000 full steps and get 10 x better accuracy. Quote Link to post Share on other sites
SirZusa 34 Posted October 31, 2011 Author Share Posted October 31, 2011 You should do this calculation on the PC using double floating point. That will fix the overflow and precision problems. The time based motion should move all the axis very close to the desired target stop position if the frequency and time calculations are all correct. The endpoint determined by the MCU should be used as the next start point by the PC to keep cumulative error under control. The advantage of a time based limit is that it keeps the ISR fast and the code simple (one time limit check instead of 3 position limit check). thats right ... it moves nearly perfect ... +/- 1 step positioning - error but the small error accumulates to a bigger one with the time i already modified it a bit more - not using the overall speed - instead it moves one axis at its maximum speed - and the others synchronized to it void set_Position_MaximumSpeed(unsigned long int x, unsigned long int y, unsigned long int z, unsigned long int maximum_speed) { // set new target positions target_x = x; target_y = y; target_z = z; // calculate difference between actual position and target position static signed long int diff_x; static signed long int diff_y; static signed long int diff_z; static double diff_max; diff_x = target_x - position_x; diff_y = target_y - position_y; diff_z = target_z - position_z; // determine directions and set them if (diff_x < 0) { ccw_x(); } else { cw_x(); } if (diff_y < 0) { ccw_y(); } else { cw_y(); } if (diff_z < 0) { ccw_z(); } else { cw_z(); } ///// if (diff_x > diff_y) { if (diff_x > diff_z) { diff_max = diff_x; } else { diff_max = diff_z; } } else { if (diff_y > diff_z) { diff_max = diff_y; } else { diff_max = diff_z; } } // calculate the speeds for each axis set_frequency_x(maximum_speed / diff_max * diff_x); set_frequency_y(maximum_speed / diff_max * diff_y); set_frequency_z(maximum_speed / diff_max * diff_z); // calculate movement time double time = diff_max * pl / maximum_speed; // and set the time set_duration(time); // set flag WORKING = 1; } you are right - i also can correct this error after the movement is complete (automatically correct an displacement) the control i built up does not support microstepping only full- and halfstep ... but really ... do i need this theoretical precision? not really ... the mechanical part will have "big" tolerances - so it makes no sense to use microstepping actually i dont need ramps - because it was only software evaluation - done with the debugger ... the ramps will be calculated on the PC later edit: its just a small demo without interfacing the PC at the moment ... i just do some trial & error - experiments now /*** DEMO ***/ set_Position_AbsoluteSpeed(2500, 5000, 10000, 25000000); while(WORKING); set_Position_MaximumSpeed(5000, 10000, 20000, 25000000); while(WORKING); set_Position_AbsoluteSpeed(10000, 15000, 30000, 25000000); while(WORKING); Quote Link to post Share on other sites
nobody 47 Posted November 1, 2011 Share Posted November 1, 2011 Microstepping is good solution for remove "jagged lines" - it add smoothness to steppers movement. My suggestion of "almost ideal" stepper controller: - Use something from MSP430F53XX or MSP430F55XX series (this serie give you advantage of USB communication) - Use 3 timers A to independent and precise frequence generating for 3 axes - Use timer B with 7 registers for synchronously generating PWM signals for microstepping controll 3 axes (two signals for axis...) - Use 3 DMA channels directed by timers A to move modified sinus tables into timer B registers to precise timed, software - independent stepper movement - Then You have full potential of processor power for interpolation computing (hardware multiplier help you a lot) - Price of F53XX or 55XX series is babu 1 Quote Link to post Share on other sites
SirZusa 34 Posted November 2, 2011 Author Share Posted November 2, 2011 As i already said - this will be a very small DIY - cnc ... the frame and mechanics will be everything but stiff - and the needed accuracy will be lower than 0.01 mm ... microstepping has good advantages ... smoother stepping, less noise ... but it has 2 main disadvantages ... 1. you need better (or lets say: more complex) control-unit .... and you need more power to compensate the losses on torque caused by the microstepping - this leading to bigger steppermotors - and as a conclusion - a higher price .... i just want to built a lowcost inbuilt usb sounds great - but i dont need it for this project - with simple uart i can control the device with every terminal ... when using usb you will need to write your own software and/or driver oPossums code works fine up to frequencies of about 90 kHz with a resolution of 0.0001 Hz ... assuming a normal stepper motor with 200 steps this makes 450 revs / second ! fullstep: 450 revs halfstep: 225 revs 1/4-steps: 112 revs 1/8-steps: 56 revs 1/16-steps: 28 revs 1/32-steps: 14 revs per second! 14 revs * 60 seconds = 840 rpm 800 rpm * 5 mm thread (circulating-ball spindle - do oyu call it like this? :shifty: ) = 4200 mm / minute ... this is more than most consumer-cnc-mills can do - and this on 1/32-steps - i only saw this configuration once in m lifetime - on a siemens-machine! so my question again: do you really need it? in my opinion more than 100 kHz output is just overkill! it gives you a theoretical precision - but in practce the mechanical part cant handle this OK ... enough of this - you showed some other benefits of the F3XXX ... synchronizing the 3 axis is just fine - but i can do this with synchronizing the SYNC-input of the L297 - and i dont need extra shift-registers - i dont know about other stepper-controls ... but maybe you need it for them i am using the PC to do all the calculations - so i dont really need hardware-multiplier .... when doing this on the MCU - you are right - then it will make a lot of things easier i think smd shouldn't be a too big problem ... but i prefer DIL for hobby-only applications --- so far - i like the discussion and it shows what possibilities are left unused here - but for this project it would be overkill for bigger projects i think i would not use stepper motors ... i would use servo-motors and incremental positioning-systems (like etched glass-scales) to move the axes to the desired positions Quote Link to post Share on other sites
SATYA 0 Posted February 19, 2013 Share Posted February 19, 2013 Hi to everyone, I am new to this blog. I recently started working on stepper motor, I have to design a 5 axial stepper motor ( control 5 stepper motors). I am thinking to use Texas instruments microcontroller and motor driver and I have to drive a single phase bipolar stepper motor with current rating of 3 amps. can anyone suggest me with microcontroller and motor driver that suits my requirement and if any one have reference design please send to e-mail - satya1312@gmail.com or post in this blog Thank you Regards Satya Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.