Motion Controller via Arduino - Page 1
Forum section: electronics / projects

author: metrologist
author_rank: Super Contributor
timestamp: March 28, 2022, 05:05:56 pm
content: Hi All, I'm a bit premature on this post as I'm just getting started, and I don't really know what I'm doing anyway. The main question is how to weave the motor control signaling in with the encoder reading in the program... Below is discussion:I would like to build a manual controller for my vertical CNC milling machine. I have the hand pendent and would like the manual controller to be independent of the PC controller (I have not been able to make the hand pendent work with the PC software...and sometimes I don't want to mess with an older Windows system anyway).The controller has a 100 position encoder and two multi-position rotary switches (6 Axis, and X1, X10, and X100 multiplier). The switch positions each just pull the corresponding parallel interface line low.Operation is simple, set the axis, multiplier, and rotate the encoder. I will add additional features such as automatic feed and whatever else can fit.The current software uses the Encoder library for Arduino (https://www.pjrc.com/teensy/td_libs_Encoder.html), where the two encoder pins are both using interrupt pins, and I am running the performance optimized mode. I have broken up the example code into functions called by the main loop:getStatus: Reads the parallel inputs and sets bool variables for the selected axis and multiplier.readEncoder: This is the code that determines if the encoder moved and the new position value. This function is broken down into if (axis) and if (multiplier) statements to apply the encoder movements to the correct axis, and by the correct amount.writeLCD: This function writes the current XYZ position and indicates the active axis and multiplier.The above functions all work very well. Now I need to figure out how to weave in the motion commands.The stepper drivers use a simple step pulse and direction inputs. I have code somewhere that handles this, including acceleration and velocity constraints, but have not looked at it in years. My first thought is that I can add a motion function call to the loop that will act on the current value of the motor's position compared to the current encoder (axis) value, and then drive the appropriate motor to the correct position.I am not certain what happens if the encoder is moved during the middle of the motion function? I think this will stop the processor from driving the motor and instead count the encoder, then the motion function will continue where it left off until complete. After that, the loop will proceed and pick up the readEncoder function.I have some other concerns about how this code operates. The encoder library can use many encoders, but I am repurposing a single encoder. This presented an issue when switching axis - a common encoder value is retained and applied to each axis. I deal with this in math by subtracting the old encoder value. It works but I am concerned there is a bug if the axis switch is changed at a certain time in the code. This is just a suspected bug...

author: moffy
author_rank: Super Contributor
timestamp: March 29, 2022, 12:09:25 am
content: Let me see if I understand the basics:1. You have a 6 axis pendant, therefore 6 stepper motors/encoders to drive.2. You want to drive them 1 axis at a time, manually at present, by the new proposed controller.3. You can read the encoder pulses.4. You haven't got the motion control software going at present.A few questions:1. What are the current ratings for the stepper motors, and what is the step angle per full step? Do you have an equivalent NEMA size for them?2. 100 pulses per revolution for the encoder seems low. Could you please confirm that.3. Won't you need at some time to be able to control multiple motors at the same time for complex shapes etc.?One or two suggestions:1. You'll need more I/O than a Teensy can provide, though the 4.1 is very powerful.2. You only need to use one interrupt pin for the encoder, the other can go on any input pin as long as we are talking about a quadrature signal. Every time an edge occurs on the interrupt pin just sample the other to determine direction.3. The motion control is going to be the most difficult part especially if it is multiaxis. That is going to be the major factor for deciding the complexity of your project.A lot of people have been doing a lot of good work in the area of CNC controllers e.g. GRBL, Marlin etc.

author: metrologist
author_rank: Super Contributor
timestamp: March 29, 2022, 05:57:02 am
content: Yes. I will do only XYZ for first release. The CNC uses ~ NEMA 42 size motors but are a different form factor. 7 Amps. The CNC part of the mill already works fine for complex shapes.The pendant encoder knob has 100 moderate physical detents, but the encoder counts to 400 in one revolution. It appears to count in 4s, but I have seen numbers in between flash if I force the dial slow between detents. The mill was originally set up for 0.001" resolution.Of course, I will need to figure out position multiplier, acceleration, and max velocity for this mill.This code here seems functional, but I am not familiar with how the stepper library works, and I do not have motors connected. I will experiment with small DRV type drivers and steppers. I have noticed that the stepper code blocks, but the encoder mostly keeps count during movements. Unless I switch axis before movement completes and I move another axis, it looses counts so not sure why. I don't have motors connected now.Code:/* Encoder Library - TwoKnobs Examplehttp://www.pjrc.com/teensy/td_libs_Encoder.htmlThis example code is in the public domain.*///OLED#include "U8glib.h"//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0); // I2C / TWIU8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI//U8GLIB_SSD1306_128X64 u8g(U8gG_I2C_OPT_NO_ACK); // Display which does not send ACint mxPos, myPos; //used for scrolling marquee at bottom of OLEDint screen = 1;#define ENCODER_OPTIMIZE_INTERRUPTS#include <Encoder.h>// Change these pin numbers to the pins connected to your encoder.// Best Performance: both pins have interrupt capability// Good Performance: only the first pin has interrupt capability// Low Performance: neither pin has interrupt capabilityEncoder enc(2, 3);// avoid using pins with LEDs attachedlong oldPos = 0;long Xpos = 0;long Ypos = 0;long Zpos = 0;long Apos = 0;int Xin = 6;int Yin = 7;int Zin = 8;int Ain = 9;int x1in = 10;int x10in = 11;int x100in = 12;bool Xen = true;bool Yen = false;bool Zen = false;bool Aen = false;int mult = 1;/*Multi-motor control (experimental)Move two or three motors at the same time.This module is still work in progress and may not work well or at all.Copyright (C)2017 Laurentiu BadeaThis file may be redistributed under the terms of the MIT license.A copy of this license has been included with this distribution in the file LICENSE.*/#include <Arduino.h>#include "BasicStepperDriver.h"#include "MultiDriver.h"#include "SyncDriver.h"// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step#define MOTOR_STEPS 200// Target RPM for X axis motor#define MOTOR_X_RPM 90// Target RPM for Y axis motor#define MOTOR_Y_RPM 90// Target RPM for Z axis motor#define MOTOR_Z_RPM 30// X motor#define DIR_X 14#define STEP_X 15// Y motor#define DIR_Y 16#define STEP_Y 17// Z motor#define DIR_Z 18#define STEP_Z 19// If microstepping is set externally, make sure this matches the selected mode// 1=full step, 2=half step etc.#define MICROSTEPS 32// 2-wire basic config, microstepping is hardwired on the driver// Other drivers can be mixed and matched but must be configured individuallyBasicStepperDriver stepperX(MOTOR_STEPS, DIR_X, STEP_X);BasicStepperDriver stepperY(MOTOR_STEPS, DIR_Y, STEP_Y);BasicStepperDriver stepperZ(MOTOR_STEPS, DIR_Z, STEP_Z);// Pick one of the two controllers below// each motor moves independently, trajectory is a hockey stick// MultiDriver controller(stepperX, stepperY);// OR// synchronized move, trajectory is a straight lineSyncDriver controller(stepperX, stepperY, stepperZ);void setup() {Serial.begin(9600);Serial.println("Encoder Test:");//OLED// flip screen, if required//u8g.setRot180();// assign default color valueif ( u8g.getMode() == U8G_MODE_R3G3B2 ) {u8g.setColorIndex(255); // white}else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {u8g.setColorIndex(3); // max intensity}else if ( u8g.getMode() == U8G_MODE_BW ) {u8g.setColorIndex(1); // pixel on}else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {u8g.setHiColorByRGB(255, 255, 255);}pinMode(Xin, INPUT_PULLUP);pinMode(Yin, INPUT_PULLUP);pinMode(Zin, INPUT_PULLUP);pinMode(Ain, INPUT_PULLUP);pinMode(x1in, INPUT_PULLUP);pinMode(x10in, INPUT_PULLUP);pinMode(x100in, INPUT_PULLUP);/*Set target motors RPM.*/stepperX.begin(MOTOR_X_RPM, MICROSTEPS);stepperY.begin(MOTOR_Y_RPM, MICROSTEPS);stepperZ.begin(MOTOR_Y_RPM, MICROSTEPS);// if using enable/disable on ENABLE pin (active LOW) instead of SLEEP uncomment next two lines// stepperX.setEnableActiveState(LOW);// stepperY.setEnableActiveState(LOW);}void loop() {getStat();getEnc();oled01();}void getStat() {Xen = digitalRead(Xin);Yen = digitalRead(Yin);Zen = digitalRead(Zin);Aen = digitalRead(Ain);if (!digitalRead(x1in)) mult = 1;if (!digitalRead(x10in)) mult = 10;if (!digitalRead(x100in)) mult = 100;}void getEnc() {long newPos;newPos = enc.read();if (newPos != oldPos) {if (!Xen) {Xpos = Xpos + mult * (newPos - oldPos);motorX(mult * (newPos - oldPos));}if (!Yen) {Ypos = Ypos + mult * (newPos - oldPos);motorY(mult * (newPos - oldPos));}if (!Zen) {Zpos = Zpos + mult * (newPos - oldPos);motorZ(mult * (newPos - oldPos));}if (!Aen) {Apos = Apos + mult * (newPos - oldPos);}oldPos = newPos;}}void serialPrint() {Serial.print("Pos = ");Serial.print(oldPos);Serial.print(", X = ");Serial.print(Xpos);Serial.print(", Y = ");Serial.print(Ypos);Serial.print(", Z = ");Serial.print(Zpos);Serial.println();Serial.println(Xen);Serial.println(Yen);Serial.println(Zen);Serial.println(Aen);Serial.print("X");Serial.println(mult);}void oled01() {// picture loopu8g.firstPage();do {draw01();}while (u8g.nextPage());mxPos = mxPos + 2;if (mxPos > 128) mxPos = 124;if (myPos > 64) myPos = 0;}uint8_t draw_state = 0;void draw01() {u8g_prepare();if (screen == 1) {//graphic commands to redraw the complete screen should be placed here//u8g.setFontPosTop();u8g.setFont(u8g_font_unifontr);if (!Xen) u8g.setFont(u8g_font_fub11); //fub11, 14, 17, 20, 25u8g.setPrintPos(0, 12);u8g.print("X: ");u8g.print(float(Xpos) / 4000, 3);u8g.setFont(u8g_font_unifontr);if (!Yen) u8g.setFont(u8g_font_fub11); //fub11, 14, 17, 20, 25u8g.setPrintPos(0, 24);u8g.print("Y: ");u8g.print(float(Ypos) / 4000, 3);u8g.setFont(u8g_font_unifontr);if (!Zen) u8g.setFont(u8g_font_fub11); //fub11, 14, 17, 20, 25u8g.setPrintPos(0, 36);u8g.print("Z: ");u8g.print(float(Zpos) / 4000, 3);u8g.setFont(u8g_font_unifontr);if (!Aen) u8g.setFont(u8g_font_fub11); //fub11, 14, 17, 20, 25u8g.setPrintPos(0, 48);u8g.print("A: ");u8g.print(float(Apos) / 4000, 3);u8g.setFont(u8g_font_unifontr);u8g.setPrintPos(96, 12);if (mult == 1) u8g.print("X1");if (mult == 10) u8g.print("X10");if (mult == 100) u8g.print("X100");u8g.drawStr(mxPos, 60, "."); //scrolling marq2uee}if (screen == 2) {}if (screen == 3) {}}void u8g_prepare(void) {u8g.setFont(u8g_font_6x10);u8g.setFontRefHeightExtendedText();u8g.setDefaultForegroundColor();u8g.setFontPosTop();}void motorX(int steps) {controller.rotate(steps, 0, 0);delay(1);}void motorY(int steps) {controller.rotate(0, steps, 0);delay(1);}void motorZ(int steps) {controller.rotate(0, 0, steps);delay(1);}void readSerial() {// if a character is sent from the serial monitor,// reset both back to zero.if (Serial.available()) {Serial.read();Serial.println("Reset knob to zero");enc.write(0);}}

author: moffy
author_rank: Super Contributor
timestamp: March 29, 2022, 07:17:11 am
content: Are you saying that the pendant has only 1 encoder and that is independent of the stepper motors? i.e. it is not a rotary encoder attached to a stepper motor.NEMA 42's are substantial motors, not your normal hobbyist size. You will need a substantial driver similar to:https://oceancontrols.com.au/SMC-014.htmland power supply to go with it. For a simple test of open loop control you could program an Arduino Uno with GRBL, then use a PC/laptop to control your XYZ axes of the pendant via GCODE commands. You would of course need drivers for the axes and power supply first.

author: H.O
author_rank: Frequent Contributor
timestamp: March 29, 2022, 06:10:06 pm
content: Ouch...this is painful to read :-)A pendant is a handheld device with an encoder wheel (often called MPG or Manual Pulse Generator), a selector switch to select which axis of the machine the encoder wheel is in control of, a selector switch to choose what distance each increment/click of the encoder wheel equals and (usually) an E-stop switch.The machine, being a full blown CNC vertical milling machine (according to the first post), obviously already have both power supply and motor drivers suitable for the motors on the machine. And since it already is a fully working CNC machine (minus pendant) it also does not need another G-code parser/controller.With that said, the code FROM something like GRBL might be useful for profile and step generation (I have zero experience with GRBL).metrologist, may I ask what PC controller this is? I know you said you don't want to but ifat allpossible to use the pendant WITH the exisiting control I'd really look into that prior to bypassing it. Think limitswitches, spindle control and what not that's already integrated in the controller.

author: metrologist
author_rank: Super Contributor
timestamp: March 29, 2022, 06:11:15 pm
content: Thanks moffy.The CNC mill is already a completed machine. I can run gcode programs and I can manually move the mill with a keyboard using the CNC software. I would rather use the hand pendant and just cannot get it to work with the CNC software, hence I will wire the hand pendant directly to the motor drivers via Arduino and use it for a manual process only.This is what the pendant looks like:https://cdn.shopify.com/s/files/1/1978/9859/products/15B4B612-C098-4aae-A672-EE4283181570_large.png?v=1563960038Signaling from the controllers are optically isolated and I should be able to simply tap Arduino step/dir signals to the electronic drivers.Maybe this is about the best I can achieve with this hardware. It only seems to have issue when there are long movements that take the machine a minute or more to complete, and I twist the axis and encoder knobs while that movement is still happening.I think I can add one more button to start/stop automatic feed on the selected axis. The other axis selections can be used to set the axis drive motor and spindle speeds with the encoder.Some people have said that the hand pendant is overrated.I must find out.

author: metrologist
author_rank: Super Contributor
timestamp: March 29, 2022, 06:27:06 pm
content: Quote from: H.O on March 29, 2022, 06:10:06 pmYes, I have tried. PC software is Mach3 and I am using parallel interface. I was not sure what the issue was, but it seemed to be the PC not seeing both parallel ports, or the SW did not see them both, or that many pins were stuck. I do know I was able to get a couple of the pins to toggle in Mach3 with the pendant switches, but it would lock up. I think I had too many things going on there and used up all the PC resources. IDK? Uncle!I am also remotivated to do this every time I boot because "You have unused icons on your desktop" and having to force shutdown or restarts as that era of Windows typically was.... and then scratch out some simple gcode commands just to make a few simple cuts. I have thought of trading for a manual mill, but I do like the CNC too.Hey, I don't have that e-Stop button so I could put an OLED display into the pendant and then just plug it directly into the driver harness. One switch and two seconds later I could be driving around a plate of aluminum.I will need a button to Zero the selected axis and will add limit stop input. That is 12 inputs and 6 (tooutputs.

author: H.O
author_rank: Frequent Contributor
timestamp: March 29, 2022, 07:55:55 pm
content: I've been using Master5/Mach1/Mach3 for as long as it's been available (do have a Mach4 license but never used it).The buffered nature of Mach3 with the LPT-port driver/engine doesn't lend itself very well to responsive MPG control, it can be made to work but not close to what it feels like on other, closer-to-realtime, hardware.Using two ports basically doubles the processing time needed by the underlying pulse engine. If you're experiencing lock-ups or bluescreens then you might need to reduce the kernel frequency and try again. Generally speaking, always use the lowest possible kernel frequency.I have two machines, on my small DIY-type mill I have just replaced the PC/Mach3/LPT-port with a chinese stand alone controller (DDCS Expert) and pendant. If you want to get rid of the PC/Windows, still have full CNC and get smooth manual control with a pendant I can recommend it. It does take minute to boot but there's no desktop, no icons, no mouse. It works but it's not AS extendable/configurable/flexible as Mach3 with it's scripting engine, GUI editor, wizards and so on. Another option is to get an external Mach3 supported motion controller that has MPG support. You could attach 3 encoders, one for each axis to get even "closer" to the manual feel (it's been done with Mach3).Sorry, I don't mean to talk you out of what you propose. I'm just afraid you'll end up with two half-assed ways of running the machine, you'll have to switch wires and connectors around, will enjoy neither and the machine will sit there unused.With that said, I'll certainly keep an eye on the thread to see what you come with!

author: metrologist
author_rank: Super Contributor
timestamp: March 29, 2022, 08:21:01 pm
content: I'm not having serious issues with the PC or Mach3. Occasionally, Windows will be locked after it boots, so I'll need to force a reboot and it usually works fine. I made a 3-ball probe and had probing routines working very well, could even probe the surface of a nickel and get a decent representative point cloud.I think I have looked at that chinese package before, and also considered UCCNC and a compatible controller. The thing is, Mach actually works for me, I just have a fiddly manual control issue. No big deal for setting axis and running gcode, not so good for manual cutting.It kind of seems all I need to do is take my Arduino breadboard out to the shop, wire up the three drivers, and give it a spin. That will be easier than digging for my little steppers/drivers and all that wiring... Oh now I remember I put a couple of those steppers on an etch-a-sketch.

author: thm_w
author_rank: Super Contributor
timestamp: March 29, 2022, 09:28:54 pm
content: Quote from: metrologist on March 29, 2022, 06:11:15 pmThen just stick with that.Google "Mach 3 USB pendant" or similar gives a number of results for products if you can't get the existing one working. Or get a proper PCI port parallel port card which has been verified to work with Mach3.Clone the HDD to a SSD, boot time will be seconds.Doing anything else is going to be a waste of time and lesson in frustration.

author: moffy
author_rank: Super Contributor
timestamp: March 30, 2022, 12:15:48 am
content: Thanks metrologist and H.O. for the explanation. What you want to achieve is quite straight forward:1. Pendant wired to an Arduino2. Arduino to provide step/direction pulses, in parallel, with the PC and MACH3 software.3. Software for the Arduino to accomplish this conversion.4. A means of paralleling the XYZ stepper pulses from each machine. Must choose one or the other.I think as you mentioned previously, any motions by the pendant controller will not be updated in the MACH3/PC. You can normally get around this by doing a coordinate reset when finished moving with the pendant. Low speed jogging shouldn't be a problem as you don't need acceleration profiles, anything more then you will need motion control, and the programming becomes much more complex.So, how confident are you with your programming skills? or do you just want to start simple and work upwards?You will need a selector/mux board, could be as simple as a 3 pole double throw switch/relay or a mux IC with a switch.You would also need to provide details as to the drivers and the expected inputs.

author: metrologist
author_rank: Super Contributor
timestamp: March 30, 2022, 02:06:44 am
content: Quote from: thm_w on March 29, 2022, 09:28:54 pmI've actually tried 3 different parallel cards and this is the 3rd PC we're on. As mentioned parallel through the PC is not ideal anyway. I've also read that you can move to a USB or Ethernet controller and use the main PP for the pendant - but still not ideal performance. There are also USB pendants that might work. If I did not have a pendant, I would not go buy one. Best to look for an entire new controller.

author: metrologist
author_rank: Super Contributor
timestamp: March 30, 2022, 02:30:53 am
content: Quote from: moffy on March 30, 2022, 12:15:48 am2: there is no need to consider the PC or Mach3 as there is no Mach or PC for this application. That might change some of your text.The drivers are looking for a step and direction signal. 5V and I think 20us pulse.I have the inputs from the pendant all wired to Arduino and all motor driver pins assigned, and I have my scope monitoring the step and direction pins are working with each axis. I think I can connect the Arduino motor pins to the mill drivers via opto-couplers and we are almost done.

author: moffy
author_rank: Super Contributor
timestamp: March 30, 2022, 02:56:41 am
content: Sounds good. So just to confirm it will only be the pendant controlling the drivers, no input wires from the PC/Mach3?There is normally a setup time i.e. the direction change has to occur a minimum set time before the step pulse, do you know what that is? Is the step line normally high or low when idling? i.e. Is a step pulse, 5V-0V-5V or 0V-5V-0V?If using optocouplers, a good idea, an isolated 5v supply will be needed for the output side. A plugpack would be suitable.I assume that you would want all motion to complete first, from the Arduino/Pendant, before responding to an axis change. You would basically ignore all inputs, except an emergency stop and the encoder (as long as the axis is the same), until the motion was completed.What controller are you using for this. An Arduino, but which type, UNO, Nano etc?What do you need the most assistance with, hardware and or software? I am comfortable and reasonably familiar with both.

author: metrologist
author_rank: Super Contributor
timestamp: March 30, 2022, 05:01:43 am
content: I started posting before I was really through the project. I was more skeptical it would work but I found a couple libraries that had most of the heavy stuff.Practically, there is a PC, but the controller is off when the PC is off, or I turn off the controller. The pendant also has an off position. Surely, nobody would ever turn them on at the same time.The driver requires 2us off, 1us on; step direction 200ns before step rise; min.And here is another way to wire the encoder to the drivers and just use Arduino to keep track of where we are.https://www.cnczone.com/forums/attachments/1/3/5/2484.attachIf I plug it in and it turns like this, I'm done.

author: moffy
author_rank: Super Contributor
timestamp: March 30, 2022, 05:46:34 am
content: If the PC is off but wired into the Driver at the same time the pendant controller is active, the PC output could either be damaged or pull the controller signals down or both. Or the reverse could happen to the controller optos, it would be best to just pass both sets of signals(6 in all) through a set of relays, reed switches should be fine. They could be on the same board as the optos and activated by the presence of the 5V opto power supply.The timing constraints are fine, but what are the voltage levels for 'off' and 'on', one assumes 'off'=0v and 'on'=5v but that's not always the case?Could you please advise as to which Arduino you have? The software solution will be dependent on the number of timers/interrupts that are available and that varies amongst the various versions as well as pinouts.

author: metrologist
author_rank: Super Contributor
timestamp: March 30, 2022, 01:43:18 pm
content: planning to use the nano. I think most of the SW is done though, unless the libraries do not work very well and the code needs a new approach.

author: moffy
author_rank: Super Contributor
timestamp: March 30, 2022, 02:32:40 pm
content: Glad to hear you are almost finished.

author: thm_w
author_rank: Super Contributor
timestamp: March 30, 2022, 09:10:44 pm
content: Quote from: metrologist on March 30, 2022, 02:06:44 amWhat chipset?From what I remember only Moschip was recommended, then you plug in the address into Mach3.https://www.machsupport.com/forum/index.php?topic=11300.0You can get a dedicated controller, the downside is losing 3D/mouse/mach3 customizations and macros.

author: metrologist
author_rank: Super Contributor
timestamp: March 30, 2022, 11:42:49 pm
content: Quote from: thm_w on March 30, 2022, 09:10:44 pmI recall looking at that Rosewill PP card. There was also another one, and some discussion of cards creating a virtual port vs. a true HW port. Looking at notes, the pendant actually worked briefly through the parallel interface, but stopped. I did things like restart Mach and it would work briefly. Then there were things like not only the port address, but which resource block it was using.Last I remember was booting up, opening Mach's diagnostics to see the 2nd port pin LEDs, and I could apply 5V or short the parallel port pins one by one and they would toggle red green or black depending on how the pin was set, but only once. Then it was all stuck.I'm running the blue screenset and Big-Tex probing routines.

author: metrologist
author_rank: Super Contributor
timestamp: March 31, 2022, 05:36:29 pm
content: Maybe not so fast...I dug out a small stepper with a Pololu drv8825 driver and got it set up. Now we can observe the issues:The main one is that the motor will briefly pause it's movement just after it starts. i.e., if I set the multiplier to X100 and jog one encoder detent, that will send 400 pulses to the motor, where we will see about 100 pulses, then a gap of about 40 pulses, then the remaining pulses will complete. Sometimes the gap is around the first 1/3 of the pulse train and sometimes it is around the second 1/3 of the train. I think Arduino is doing something else during that gap.I removed the stepper driver library and created a simpler for loop to address this gap. It did not fix the issue, but now I have a for loop that handles driving the motor, and I can easily add a short acceleration/deceleration routine to it. Saved me a lot of program space...The second issue is the encoder detents. It feels like a quality encoder and is smooth, but the physical detent valley's seem wider than the encoder gaps. What happens is if I try to move one detent (X1 multiplier), the knob will overshoot the detent valley. Remember that each detent sends 4 pulses, so when you slightly pass the detent, and extra pulse or two is sent, and then when the encoder settles back into the valley, an additional step or two is sent in the reverse direction. It's like switch bouncing. If I work very hard turning the encoder then I can get a smooth run without any wiggle around the detents. I might remove the detent and go with friction instead.The good news is that I jerked the encoder back and forth quite aggressively, taking many spins around the block back and forth, and wiggling it around, and only occasionally did the motor get out of sync with the displayed position. Those are not real-world use cases though.Now I still have plenty of room to work with, almost 50% of program space left, and I'm sure I could streamline what I have quite a bit. I still have 4 IO pins and the encoder has the 5th and 6th axis available for something. Actually I already set up some of this:5th axis will change the stepper motor speed, which is displayed in Inches per Minute (ipm)6th axis can control the spindle RPMTechnically, the encoder Off position could be used for a function in conjunction with encoder or any other buttonButton to zero the selected axis, which could also select stepper/spindle speed presets)Button to start/stop automatic feed on the selected axis, which could also toggle stepper speed between min/max, and turn on/off the spindleLimit and E-stop input from machineOne more input left...

author: H.O
author_rank: Frequent Contributor
timestamp: March 31, 2022, 05:54:24 pm
content: Have a counter keep track of the encoder in its pure resolution, ie 4 counts per detent.Divide that counter value by 4, giving you one count up/down per detent and use the result. Make sure to use integer math (or simply right shift two places) so that anything less than 4 counts simply gets truncated. That should filter out the bouncing happening as the encoder settles in the detents. Always recalculate from the "pure resolution counter".Make sure that the counter is able to keep up with the encoder at the highest speed you can possibly spin it.

author: metrologist
author_rank: Super Contributor
timestamp: March 31, 2022, 06:43:04 pm
content: I am sending the same changes that the existing counter is detecting. I had thought of keeping a display counter (which is what I have, but converted to inch position) and a second motor position counter, and then drive the motor to the display position every time rather than move a certain amount. That could eliminate the motor position errors I could occasionally achieve. There is some overhead in that. I tried simple division and yeah I need to do integer math. That might help quite a bit the way things are.

author: rstofer
author_rank: Super Contributor
timestamp: March 31, 2022, 07:32:20 pm
content: I use Mach3 with a SmoothStepper (ethernet version) and although this isn't the pendant I use (I only need 3 axis), it's where I would start.https://www.amazon.com/T-king-Wireless-Pendant-Handwheel-Controller/dp/B085NQY8C6Mach3 already includes MPG capability.https://warp9td.com/https://www.machsupport.com/software/mach3/https://www.automationtechnologiesinc.com/products-page/digital-stepper-motor-driver/digital-stepper-driver-kl-8070d-heat-sink-is-includedThere are a number of grbl projects for MPGs on the web. Some wind up using multiple CPUsAlthough I could have used any PC, I chose an industrial computer from Logic Supply and put the entire project in a PC case. Computer, 48V supply, drivers, stepper and all the bits. Required power supplies were DIN rail mounted. Today I would probably use an Intel NUC.This was not a constrained budget type of project. I had an end goal in mind and I met it.

author: metrologist
author_rank: Super Contributor
timestamp: April 05, 2022, 07:58:38 pm
content: Yes, money would solve all problems. The problem is where do you draw the line? I stopped after a couple more parallel cards, but smoothstepper, pokeys, and other controllers/pendants were considered (i.e., how about a USB pendant with what have?) ATM I'm just worn out fiddling with it in Mach.The Arduino manual controller is actually working quite well. After getting the motor tuning, and switching to an actual 200PPR stepper, the action works quite well. I'm considering dumping the encoder library and just coding the interrupt, but only if I need more program space. In the end, it's actually not all that impressive as it just interprets encoder steps and passes them to the stepper with a direction signal.I've not been able to figure out what causes the motor step function for loop to pause while cycling through its count, but it does it every time. I think it wont matter because actual cutting is not likely to be using a large multiplier so small number of steps are counted and sent to the motor function, and at least I have not observed a pause there.

author: rstofer
author_rank: Super Contributor
timestamp: April 06, 2022, 03:11:11 pm
content: Quote from: metrologist on March 31, 2022, 06:43:04 pmThat error method of control is called 'following error control' (the control position is ahead of the motor position and the motor is following along) and was used in early numerical control (and may still be) where the error generates the current that moves the servo valve for the hydraulic motor. When the error is zero, the valve is closed otherwise flow is linear with current over some range. As the following error increases so does the motor speed. This may still be the accepted practice for servo operated machines. I haven't followed along.Stepper motor control doesn't often use feedback. It is assumed that the motor can step against the load and that it never misses steps. If the motors do lose step and are corrected with encoder feedback, multi-axis cuts may not come out right.

author: metrologist
author_rank: Super Contributor
timestamp: April 06, 2022, 05:00:28 pm
content: Quote from: rstofer on April 06, 2022, 03:11:11 pmYeah, no feedback system here. What I meant to describe is that I have a pulse pass-through engine now. The change would be to run two independent counters, one that counts the encoder and feeds the display (pass-through incremental changes), and also feeds the motor drive but the motor drive function does not simply push incremental changes, but rather counts absolute motor position and calculates a new position based on the incremental inputs.The current encoder library buffers encoder counts, so axis switches must wait until the current axis move completes. Otherwise, the buffered encoder counts will be applied to the new axis when the current motor drive loop completes and the main loop cycles through again. It seems I need a little routine to check if the interrupt counter has some counts left over when I check the status of the hand pendant switches at the beginning of the main loop. I do not know how to do that, if that is actually what is happening.

author: metrologist
author_rank: Super Contributor
timestamp: April 08, 2022, 04:18:04 pm
content: pic