![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Code to drive a CNC machine via a PC LPT port lookalike 25 pin 'D', experiment in 'PC/Mach3' replacement. Designed to compile and run on mbed LPC1768, Freescale KL25Z and Freescale KL46Z. Proved on LPC1768 and KL25Z, problem with serial port on KL46Z. Reads subset of 'G Codes' through usb/serial port and drives 3 stepper/servo drives for X, Y and Z, also similar Step/Dir outputs for spindle motor control. Emulates PC LPT, outputs 'charge pump', proved driving Seig KX3 CNC mill
main.cpp
- Committer:
- JonFreeman
- Date:
- 2014-02-20
- Revision:
- 2:b3c668ec43ac
- Parent:
- 1:66ee619f206b
- Child:
- 3:7aaf0072cc22
File content as of revision 2:b3c668ec43ac:
#include "mbed.h" #include "rtos.h" #include "MODSERIAL.h" #include "cnc.h" using namespace std; extern void command_line_interpreter (void const *) ; //extern void lissajous (void const *) ; extern double feed_rate, spindle_rpm; extern void more_setup () ; extern struct Gparams last_position; const int BAUD = 38400; MODSERIAL pc(USBTX, USBRX); // tx, rx to pc //Serial pc(USBTX, USBRX); // tx, rx to pc Ticker NCO_gen; // Ticker generating interrupts at "Kernel Speed", NCO updating frequency (about 40kHz) bool running = false, new_run_pending = false, idle = false, move_ended = false; volatile unsigned long ticks = 0L; // 32 bit count of "interrupt_period_us" interrupts from time t=0 unsigned long tickrun = 0L; // 32 bit effectively stores time in future when current movement to stop unsigned long ticks_next = 0L; // 32 bit effectively stores time in future when current movement to stop unsigned long millisecs = 0L; // 32 bit unsigned long pir_a = 0L, // Phase Increment Registers pir_x = 0L, pir_y = 0L, pir_z = 0L, pir_a_next = 0L, // Data for next move assembled here pir_x_next = 0L, // during a move. pir_y_next = 0L, // This way, next move can start immediately pir_z_next = 0L, // on end of current move - minimised jerking pir_spin = 0L; // Referenced only in command_interpreter as spindle speed setting #if defined (TARGET_KL25Z) const char Target[] = "KL25Z"; DigitalOut intled (PTE1); //J2p20 DigitalOut charge_pumpD25pin1 (PTE0); //J2p18 // InterruptIn D25pin10_EStop (PTE20); //j10p1 KL25 J10 is KL46 j4 DigitalIn D25pin10_EStop (PTE20); //j10p1 KL25 J10 is KL46 j4 DigitalIn D25pin11_XLim (PTE21); //j10p3 DigitalIn D25pin12_YLim (PTE22); //j10p5 DigitalIn D25pin13_ZLim (PTE23); //j10p7 DigitalIn D25pin15_unkn (PTE30); //j10p11 //SPISlave spidevice(PTD3, PTD2, PTD1, PTD0); // mosi, miso, sclk THIS TURNS LED ON BLUE ! (uses p11, p12, p13 on mbed LPC) SPISlave spidevice(PTD2, PTD3, PTD1, PTD0); // mosi, miso, sclk THIS TURNS LED ON BLUE ! (uses p11, p12, p13 on mbed LPC) // J2p08,J2p10,J2p12, J2p06 //SPI spidevice(PTD2, PTD3, PTD1); // mosi, miso, sclk THIS TURNS LED ON BLUE ! (uses p11, p12, p13 on mbed LPC) //SPI spidevice(PTD3, PTD2, PTD1); // mosi, miso, sclk THIS TURNS LED ON BLUE ! (uses p11, p12, p13 on mbed LPC) //NOTE doubt possibly miso mosi in wrong order here, PTD3 and PTD2 #define STEPPER_PORT PortC const int PortBitXSt = 3, // Port bit num X Step J1P05 D25pin 2 PortBitXDi = 4, // Port bit num X Dir J1P07 D25pin 3 PortBitYSt = 5, // Port bit num Y Step J1P09 D25pin 4 PortBitYDi = 6, // Port bit num Y Dir J1P11 D25pin 5 PortBitZSt = 10, // Port bit num Z Step J1P13 D25pin 6 PortBitZDi = 11, // Port bit num Z Dir J1P15 D25pin 7 PortBitASt = 12, // Port bit num A Step J2P01 D25pin 8 PortBitADi = 13, // Port bit num A Dir J2P03 D25pin 9 PortBitSSt = 8, // Port bit num Spin Step J1P14 D25pin 14 PortBitSDi = 9; // Port bit num Spin Dir J1P16 D25pin 16 #endif #if defined (TARGET_KL46Z) const char Target[] = "KL46Z"; DigitalOut intled (PTE1); //J2p20 checked DigitalOut charge_pumpD25pin1 (PTE0); //J2p18 checked // InterruptIn D25pin10_EStop (PTE20); // j4p1 KL46 J4 is KL25 J10 DigitalIn D25pin10_EStop (PTE20); // j4p1 KL46 J4 is KL25 J10 checked DigitalIn D25pin11_XLim (PTE21); // j4p3 checked DigitalIn D25pin12_YLim (PTE22); // j4p5 checked DigitalIn D25pin13_ZLim (PTE23); // j4p7 checked DigitalIn D25pin15_unkn (PTE30); // j4p11 checked SPISlave spidevice(PTA16, PTA17, PTA15, PTA14); // mosi, miso, sclk, ssel (uses p11, p12, p13, p? on mbed LPC) // J2p13, J2p15, J2p11, J2p09 // Easy way to allocate port bits for // output of stepper motor Step and DIR sigs #define STEPPER_PORT PortC const int PortBitXSt = 0, // Port bit num X Step J1P05 D25pin 2 checked PortBitXDi = 4, // Port bit num X Dir J1P07 D25pin 3 checked PortBitYSt = 6, // Port bit num Y Step J1P09 D25pin 4 checked PortBitYDi = 7, // Port bit num Y Dir J1P11 D25pin 5 checked PortBitZSt = 10, // Port bit num Z Step J1P13 D25pin 6 checked PortBitZDi = 11, // Port bit num Z Dir J1P15 D25pin 7 checked PortBitASt = 13, // Port bit num A Step J2P01 D25pin 8 checked PortBitADi = 16, // Port bit num A Dir J2P03 D25pin 9 checked PortBitSSt = 8, // Port bit num Spin Step J1P14 D25pin 14 checked PortBitSDi = 9; // Port bit num Spin Dir J1P16 D25pin 16 checked #endif #if defined (TARGET_MBED_LPC1768) const char Target[] = "MBED LPC1768"; DigitalOut intled(LED2); // Correct DigitalOut charge_pumpD25pin1 (p25); //J2p18 Following 5 inputs all wrong - TO DO sort which pins // InterruptIn D25pin10_EStop (p26); //P2.0 DigitalIn D25pin10_EStop (p26); //P2.0 DigitalIn D25pin11_XLim (p24); //P2.2 DigitalIn D25pin12_YLim (p23); //P2.3 DigitalIn D25pin13_ZLim (p19); //P1.30 DigitalIn D25pin15_unkn (p20); //P1.31 SPISlave spidevice(p5, p6, p7, p8); // Easy way to allocate port bits for *** N O T CHECKED for MBED_LPC1768 *** // output of stepper motor Step and DIR sigs #define STEPPER_PORT Port0 /* Port 0 bits routed to DIP pins as follows:- P0.00 p09 Reserve SDA P0.01 p10 Reserve SCL P0.04 p30 CAN rd - USE X Step D25pin 2 P0.05 p29 CAN td - USE X Dir D25pin 3 P0.10 p28 SDA - USE Y Step D25pin 4 P0.11 p27 SCL - USE Y Dir D25pin 5 P0.15 p13 Tx - USE Z Step D25pin 6 P0.16 p14 Rx - USE Z Dir D25pin 7 P0.17 p12 miso - USE A Step D25pin 8 P0.18 p11 mosi - Use A Dir D25pin 9 P0.23 p15 A In - Use S Step D25pin 14 P0.24 p16 A In - Use S Dir D25pin 16 P0.25 p17 Reserve A In P0.26 p18 Reserve A Out */ const int PortBitXSt = 4, // Port bit num X Step PortBitXDi = 5, // Port bit num X Dir PortBitYSt = 10, // Port bit num Y Step PortBitYDi = 11, // Port bit num Y Dir PortBitZSt = 15, // Port bit num Z Step PortBitZDi = 16, // Port bit num Z Dir PortBitASt = 17, // Port bit num A Step PortBitADi = 18, // Port bit num A Dir PortBitSSt = 23, // Port bit num Spin Step PortBitSDi = 24; // Port bit num Spin Dir #endif const long // Assemble mask bits from now known port bit positions XSt = 1 << PortBitXSt, // X axis Step signal XDi = 1 << PortBitXDi, // X axis Direction signal YSt = 1 << PortBitYSt, // Y axis Step, etc YDi = 1 << PortBitYDi, ZSt = 1 << PortBitZSt, // Z axis ZDi = 1 << PortBitZDi, ASt = 1 << PortBitASt, // A axis, not implemented in full, for e.g. rotary axis ADi = 1 << PortBitADi, SDi = 1 << PortBitSDi, // Spindle, also driven by Step and Dir signals up to 5kHz SSt = 1 << PortBitSSt, // for 5000 RPM SM_MASK = (XSt | XDi | YSt | YDi | ZSt | ZDi | ASt | ADi | SDi | SSt); PortOut Steppers (STEPPER_PORT, SM_MASK); const long direction_swappers = XDi | YDi | ZDi | SDi; // include bit to swap direction /* long read () { return mysteppers ^ direction_swappers; } void write (long val) { mysteppers = val ^ direction_swappers; } */ class digital_readout_stuff { // class does not need to be named here private: char * readout (char * txt, long p) // p has running subtotal of all pulses issued to stepper driver { txt[0] = '+'; // constructs string e.g. "+123.456" txt[8] = 0; // null terminated if (p < 0) { txt[0] = '-'; p = -p; } p *= 1000; p /= pulses_per_mm; if (p > 999999) { sprintf(txt + 1, "OVRANGE"); return txt; } for(int k = 7; k > 0; k--) { if (k == 4) txt[k] = '.'; else { txt[k] = '0' + (p % 10); p /= 10; } } return txt; // Returns pointer unaltered for subsequent use by e.g. cout } public: signed long x, y, z, a; // Could easily expand up to six or more dros bool dro_output; // To enabe / disable output to terminal void init () { x = y = z = a = 0; // These dro registers count pulses delivered to stepper motor driver dro_output = true; } void update () { static long t = 300; // Prevent display immediately upon startup if (millisecs < t) return; if(!idle && dro_output) { char txt[12]; pc.printf("dros X %s,", readout(txt, x)); // dro.n has running subtotal of all pulses issued to stepper driver.n pc.printf(" Y %s, Z ", readout(txt, y)); pc.printf("%s, %s\r\n", readout(txt, z), running ? "R":"idle"); if(!running) idle = true; // Purpose of idle flag is to stop dro updates JUST AFTER run completes. t = millisecs + 350; // Schedule next update after this non-blocking delay } } } dro_out ; const int PIRBUFFSIZE = 40; // pirbufgrain are 40 bytes each class circbuff { private: pirbufgrain grain [PIRBUFFSIZE + 1]; int OnPtr, OffPtr; bool bufffull, buffempty, buffhalf; void setempty () { bufffull = false; buffhalf = false; buffempty = true; } void grain_copy (pirbufgrain & src, pirbufgrain & dest) { dest.x = src.x; dest.y = src.y; dest.z = src.z; dest.c = src.c; dest.f_rate = src.f_rate; // int feed rate mm per min * 1000 } public: void init () { OnPtr = OffPtr = 0; setempty (); } int On_Q () { int k; if (bufffull) return PIRBUFFSIZE; k = OnPtr - OffPtr; if (k < 0) k += PIRBUFFSIZE; if (k > PIRBUFFSIZE / 2) buffhalf = true; else buffhalf = false; return k; } bool readable () {return !buffempty; } bool writeable () {return !bufffull; } bool read (pirbufgrain & g) { // if (buffempty) return false; // TO DO Fix problem with buffempty flag if (On_Q() == 0) return false; bufffull = false; grain_copy (grain[OffPtr++], g); if (OffPtr >= PIRBUFFSIZE) OffPtr = 0; if (OnPtr == OffPtr) buffempty = true; return true; } bool write (pirbufgrain & g) { if (bufffull) return false; buffempty = false; grain_copy (g, grain[OnPtr++]); if (OnPtr >= PIRBUFFSIZE) OnPtr = 0; if (OnPtr == OffPtr) bufffull = true; return true; } } CircBuff; int PutMoveOnList (struct pirbufgrain & s) { while (!CircBuff.writeable()) osThreadYield(); CircBuff.write (s); // pc.printf("CircBuff, contains %d\r\n", CircBuff.On_Q()); return 0; } const double duration_multiplier = 60000000.0 / interrupt_period_us; void move_to_XYZ (struct pirbufgrain & ins) { struct pirbufgrain outs; double distx = ins.x - last_position.x.dbl, disty = ins.y - last_position.y.dbl, distz = ins.z - last_position.z.dbl, distT = sqrt ((distx * distx) + (disty * disty) + (distz * distz)), // 3D Pythag ! temp = n_for_onemmpermin / distT; if (distT < 0.01) { pc.printf("Very small move %.4f, Ignoring!\r\n", distT); return; } last_position.x.dbl = ins.x; // Update global last_position record last_position.y.dbl = ins.y; last_position.z.dbl = ins.z; outs.f_rate = ins.f_rate; outs.c = duration_multiplier * distT; // Duration ticks subject to feed rate compo outs.x = temp * distx; outs.y = temp * disty; outs.z = temp * distz; // Have assembled data ready to put onto queue of move instructions PutMoveOnList (outs); } void target_cmd (struct singleGparam * a) { pc.printf("Computer is %s\r\n", Target); } /* * Interrupt Service Routine */ /* **** UNBROKEN VERSION 6th Feb 2014 ****************** void Numerically_Controlled_Oscillators_ISR () { // services Ticker 'NCO_gen' generated interrupts ***ISR*** static const int millisec_countdown = 1000 / interrupt_period_us; const long bit_lutx[4] = {XSt0 | XDi0, XSt0 | XDi1, XSt1 | XDi1, XSt1 | XDi0}, // Used to look-up 'clk' and 'dir' signals from accum MSBs bit_luty[4] = {YSt0 | YDi0, YSt0 | YDi1, YSt1 | YDi1, YSt1 | YDi0}, // Used to look-up 'clk' and 'dir' signals from accum MSBs bit_lutz[4] = {ZSt0 | ZDi0, ZSt0 | ZDi1, ZSt1 | ZDi1, ZSt1 | ZDi0}, // Used to look-up 'clk' and 'dir' signals from accum MSBs bit_luta[4] = {ASt0 | ADi0, ASt0 | ADi1, ASt1 | ADi1, ASt1 | ADi0}, // Used to look-up 'clk' and 'dir' signals from accum MSBs bits2shift = (sizeof (long) << 3) - 2, static unsigned long // acc_s = 0L, // For Spindle motor, probably not needed as may be pwm acc_a = 0L, acc_x = 0L, acc_y = 0L, acc_z = 0L; static int obitz = 0, mscount = millisec_countdown; int oldbitz, acts; intled = 1; // LED on for duration of interrupt service - point for scope probing ticks++; // count of interrupts serviced if(!--mscount) { // Maintain global counter of elapsed milli seconds mscount = millisec_countdown; millisecs++; } if (running) { acc_x += pir_x; // Update phase of signals in accumulators acc_y += pir_y; acc_z += pir_z; acc_a += pir_a; // not yet implemented // acc_s += pir_s; // pir_s used for spindle speed oldbitz = obitz; // pin output levels as determined during previous interrut obitz = bit_lutx[acc_x >> bits2shift] | bit_luty[acc_y >> bits2shift] | bit_lutz[acc_z >> bits2shift] | bit_luta[acc_a >> bits2shift]; mysteppers = obitz; // Output signals to stepper motor drivers, next look for _- pos clk events on 'Step' outputs acts = (~oldbitz & obitz); // get pos clk edge triggers 'Step' bits acts |= (obitz & (XDi1 | YDi1 | ZDi1)); // get axis X, Y and Z Direction bits if(acts & XSt1) { // got pos clk edge for axis X if (acts & XDi1) dro.x++; else dro.x--; } if(acts & YSt1) { // got pos clk edge for axis Y if (acts & YDi1) dro.y++; else dro.y--; } if(acts & ZSt1) { // got pos clk edge for axis Z if (acts & ZDi1) dro.z++; else dro.z--; } if (tickrun <= ticks) { // End of a machine movement detected, start next move here if possible running = false; move_ended = true; pir_x = 0L; // stop all stepper motors pir_y = 0L; pir_z = 0L; pir_a = 0L; // ticks = 0L; // Simply to avoid having to think about overflow problems } } else { // Not running. Grab next data here when or if available if (new_run_pending) { // Pick up on flag set elsewhere pir_a = pir_a_next; pir_x = pir_x_next; pir_y = pir_y_next; pir_z = pir_z_next; tickrun = ticks + ticks_next; running = true; // Start the new run new_run_pending = false; // Clear the flag which initiated this update idle = false; } } charge_pump = ticks & 0x02; intled = 0; // LED off } // end of interrupt handler */ /* * End of Interrupt Service Routine */ /* * Interrupt Service Routine */ #define STEP_IDLE_HI //#define STEP_IDLE_LO void Numerically_Controlled_Oscillators_ISR () { // services Ticker 'NCO_gen' generated interrupts ***ISR*** static const int millisec_countdown = 1000 / interrupt_period_us; const long step_mask = ASt | XSt | YSt | ZSt, // Added 6th Feb 14 Mask Does NOT include spindle bits dir_mask = ADi | XDi | YDi | ZDi; // Added 6th Feb 14 Mask Does NOT include spindle bits static unsigned long acc_spin = 0L, acc_a = 0L, acc_x = 0L, acc_y = 0L, acc_z = 0L; static long mscount = millisec_countdown; static long dir_bits = 0L, oldSteps = 0L; // Added 6th Feb 14 long acts, tmp, newSteps, stbits; intled = 1; // LED on for duration of interrupt service - point for scope probing ticks++; // count of interrupts serviced if(!--mscount) { // Maintain global counter of elapsed milli seconds mscount = millisec_countdown; millisecs++; } acc_spin += pir_spin; tmp = Steppers ^ direction_swappers; #if defined STEP_IDLE_LO tmp &= ~step_mask; // Step bits prepared for idle lo #endif #if defined STEP_IDLE_HI tmp |= step_mask; // Step bits prepared for idle hi #endif if (acc_spin & 0x80000000) { tmp |= SSt; } else { tmp &= ~SSt; } // mysteppers = tmp; if (running) { acc_x += pir_x; // Update phase of signals in accumulators acc_y += pir_y; acc_z += pir_z; acc_a += pir_a; // not yet implemented newSteps = 0L; // Added 6th Feb 14 if (acc_a & 0x80000000) newSteps |= ASt;// Added 6th Feb 14 if (acc_x & 0x80000000) newSteps |= XSt;// Added 6th Feb 14 if (acc_y & 0x80000000) newSteps |= YSt;// Added 6th Feb 14 if (acc_z & 0x80000000) newSteps |= ZSt;// Added 6th Feb 14 stbits = newSteps ^ oldSteps; // Any bit of stbits set to initiate a Step pulse acts = dir_bits | stbits; // oldSteps = newSteps; // Added 6th Feb 14 // tmp = acts ^ step_mask; // Invert clock - Arc Euro stepp motor driver only goes into half current mode this way tmp ^= stbits; Steppers = tmp ^ direction_swappers; // Output signals to stepper motor drivers, next update dros from 'clocked' bits CLOCK IDLES HIGH if(acts & XSt) { // got clk edge for axis X if (acts & XDi) dro_out.x--; else dro_out.x++; } if(acts & YSt) { // got clk edge for axis Y if (acts & YDi) dro_out.y--; else dro_out.y++; } if(acts & ZSt) { // got clk edge for axis Z if (acts & ZDi) dro_out.z--; else dro_out.z++; } if (tickrun <= ticks) { // End of a machine movement detected, start next move here if possible if (new_run_pending) { pir_a = pir_a_next; pir_x = pir_x_next; pir_y = pir_y_next; pir_z = pir_z_next; dir_bits = 0; // Added 6th Feb 14 if (pir_a & 0x80000000) dir_bits |= ADi;// Added 6th Feb 14 read sign bits if (pir_x & 0x80000000) dir_bits |= XDi;// Added 6th Feb 14 if (pir_y & 0x80000000) dir_bits |= YDi;// Added 6th Feb 14 if (pir_z & 0x80000000) dir_bits |= ZDi;// Added 6th Feb 14 acts = Steppers ^ direction_swappers; // read output lines acts &= ~dir_mask; acts |= dir_bits; Steppers = acts ^ direction_swappers; tickrun = ticks + ticks_next; running = true; // Start the new run new_run_pending = false; // Clear the flag which initiated this update idle = false; } // End of if (new_run_pending) { else { // End of machine movement AND no new_run_pending running = false; move_ended = true; pir_x = 0L; // stop all stepper motors pir_y = 0L; pir_z = 0L; pir_a = 0L; // ticks = 0L; // Simply to avoid having to think about overflow problems } } } else { // Not running. Grab next data here when or if available Steppers = tmp ^ direction_swappers; if (new_run_pending) { // Pick up on flag set elsewhere pir_a = pir_a_next; pir_x = pir_x_next; pir_y = pir_y_next; pir_z = pir_z_next; dir_bits = 0; // Added 6th Feb 14 if (pir_a & 0x80000000) dir_bits |= ADi;// Added 6th Feb 14 read sign bits if (pir_x & 0x80000000) dir_bits |= XDi;// Added 6th Feb 14 if (pir_y & 0x80000000) dir_bits |= YDi;// Added 6th Feb 14 if (pir_z & 0x80000000) dir_bits |= ZDi;// Added 6th Feb 14 acts = Steppers ^ direction_swappers; // read output lines acts &= ~dir_mask; acts |= dir_bits; Steppers = acts ^ direction_swappers; tickrun = ticks + ticks_next; running = true; // Start the new run new_run_pending = false; // Clear the flag which initiated this update idle = false; } // end of if (new_run_pending) { // Pick up on flag set elsewhere } // end of else { // Not running. Grab next data here when or if available charge_pumpD25pin1 = ticks & 0x01; // Can use 0x01 or 0x02 here to alter charge pump freq intled = 0; // LED off } // end of interrupt handler /* * End of Interrupt Service Routine */ bool spindle_running () { return pir_spin; } void spindle_control (double ss) { long t, p; pir_spin = (signed long) (ss * spindle_factor); t = ticks; while (t == ticks) {} // wait until just after next interrupt p = Steppers ^ direction_swappers; if (pir_spin & 0x80000000) p |= SDi; else p &= ~SDi; Steppers = p ^ direction_swappers; pc.printf("Done setting spindle speed %.0f, delay = %d\r\n", ss, ticks - t); } /* void scmd (struct singleGparam * a) { long t, p; if (fabs(a[1].dbl) > spindle_max) { pc.printf ("Errror setting spindle RPM, can't set to %.0f, ignoring request\r\n", a[1].dbl); return; } pc.printf ("Setting spindle RPM to %.0f Can set Pos or Neg for fwd/rev\r\n", a[1].dbl); pir_spin = (signed long) (a[1].dbl * spindle_factor); t = ticks; while (t == ticks) {} // wait until just after next interrupt p = mysteppers; if (pir_spin & 0x80000000) p |= SDi; else p &= ~SDi; mysteppers = p; pc.printf("Done setting spindle, delay = %d", ticks - t); } */ void newpir_updater (void const * name) { static long x, y, z;//, count = 0; struct pirbufgrain outs; // pc.printf("Arrived at newpir_updater\r\n"); while (true) { // while (!move_ended || !CircBuff.readable()) { ** TO DO ** Solve problem with empty flag while (!move_ended || CircBuff.On_Q() == 0) { osThreadYield(); } // Proceed beyond here only when move_ended AND CircBuff.readable() both TRUE CircBuff.read(outs); x = (long)(outs.f_rate * outs.x); // These take much CPU time !! y = (long)(outs.f_rate * outs.y); z = (long)(outs.f_rate * outs.z); ticks_next = (unsigned long)(outs.c / outs.f_rate); pir_x_next = x; pir_y_next = y; pir_z_next = z; move_ended = idle = false; new_run_pending = true; // cleared and 'running' flag set in interrupt handler // idle = false; // count++; // pc.printf("CircB tot %d\r\n", count); } } void flags_report_cmd (struct singleGparam * a) { // Diagnostic helper function pc.printf("Flags Report\r\nRunning %s\r\n", running ? "T":"F"); pc.printf("idle %s\r\n", idle ? "T":"F"); pc.printf("new_run_pending %s\r\n", new_run_pending ? "T":"F"); pc.printf("move_ended %s\r\n", move_ended ? "T":"F"); pc.printf("CircBuff.readable() %s\r\n", CircBuff.readable() ? "T":"F"); pc.printf("On CircBuff %d\r\n", CircBuff.On_Q()); } /*void taskone (void const * name) { static int i = 0; while (true) { pc.printf("%s %d\r\n", name, i++); Thread::wait(9500); osThreadYield(); } } void tasktwo (void const * name) { pc.printf("Task Two runs once and exits\r\n"); Thread::wait(700); osThreadYield(); } void taskthree (void const * name) { static int i = 0; while (true) { pc.printf("%s %d\r\n", name, i++); Thread::wait(3500); osThreadYield(); } }*/ /* #define ESTOP 0x100 #define XLIM 1 #define YLIM 2 #define ZLIM 4 #define UNKN 8 */ class inputsreaderstuff { private: long ins_now;//, ins_old, ins_changed; public: void init () { ins_now = 0L;}//ins_old = ins_changed = 0L; } long read () { ins_now = 0; if (D25pin10_EStop) ins_now |= ESTOP; if (D25pin11_XLim) ins_now |= XLIM; if (D25pin12_YLim) ins_now |= YLIM; if (D25pin13_ZLim) ins_now |= ZLIM; if (D25pin15_unkn) ins_now |= UNKN; // ins_changed = ins_now ^ ins_old; // ins_old = ins_now; return ins_now; } // long changed () { return ins_changed; } } Inputs_From_Machine; void report_inputs () { long i = Inputs_From_Machine.read(); pc.printf("Inputs: EStop %d, XLim %d, YLim %d, ", i & ESTOP ? 1:0, i & XLIM ? 1:0, i & YLIM ? 1:0); pc.printf("ZLim %d, unkn %d\r\n", i & ZLIM ? 1:0, i & UNKN ? 1:0); } //void Emergency_Stop_Interrupt () { // pc.printf("Emergency Stop Activated !!\r\n"); // spindle_control (0.0); // Stop spindle rotation //} int main() { pc.baud(BAUD); // comms to 'PuTTY' serial terminal via mbed usb // D25pin11_XLim.mode (PullDown); External resistors now fitted // D25pin12_YLim.mode (PullDown); // D25pin13_ZLim.mode (PullDown); // D25pin15_unkn.mode (PullDown); // D25pin10_EStop.mode (PullDown); // D25pin10_EStop.rise (& Emergency_Stop_Interrupt); // D25pin10_EStop.fall (& Emergency_Stop_Interrupt); more_setup () ; // Zeros one 'pirs' structure 'last_position' dro_out.init(); CircBuff.init (); Inputs_From_Machine.init (); spidevice.format(8, 0); // 8 bits mode 0, // p11 mosi, p12 miso, p13 sclk ** ONLY 8 BIT ** spidevice.frequency(12000000); // 12MHz bit rate pc.printf("\r\n*\n*\nFound Computer %s\r\n", Target); pc.printf("Welcome to the CNC tester\r\nStep pulses required to move 1.0mm = %9.0f\r\n", pulses_per_mm); pc.printf("PIR 'n' for 1mm per min = %9.0f\r\ntop speed = %6.1f mm per min\r\n\n", n_for_onemmpermin, max_mm_per_min); NCO_gen.attach_us(&Numerically_Controlled_Oscillators_ISR, (long)interrupt_period_us);// Have setup timed interrupts, let other code deal // Thread threadnametaskone (taskone, (void *)"task one stuff"); // Thread t8 (tasktwo, (void *)"task two"); Thread tsr2 (newpir_updater, (void *)"read from CircBuff and move"); // Thread tthree (taskthree, (void *)"task three"); // Thread patterngen (lissajous, (void *)"Loading Lissajous") ; Thread comlin (command_line_interpreter, (void *)"cli"); // Read any instructions arriving via serial port and act upon them long ins, ins_old, ins_changed = 0; ins = ins_old = Inputs_From_Machine.read (); move_ended = true; // Needed to kickstart system while(1) { // Round Robin loop dro_out.update (); // Update DRO readings if, and as often as needed ins = Inputs_From_Machine.read (); ins_changed = ins ^ ins_old; ins_old = ins; if (ins_changed) pc.printf("Inputs Have Changed 0x%x, read 0x%x\r\n", ins_changed, ins); // pc.printf("."); osThreadYield(); // } // end of Round Robin loop } // end of int main()