Electronic Spiral Cutter for my Mill - in progress

drrags

H-M Supporter - Silver Member
H-M Supporter - Silver Member
Joined
May 13, 2021
Messages
26
A while back I posted a question on why my Rube Goldberg contraption wasn't cutting spirals (here). I learned that I need to move the table while I rotate the piece, so I went on a mission to learn how to do that. Since, at the time, I didn't know the proper phrases for what I was looking for, my google-fu pretty much sucked and I wasn't really finding anything that I could apply. The mechanical examples were interesting, but I would be locked into certain gear ratios and I saw a couple of videos of an electronic "transmission", but no details were exposed. It was at this point that my ignorance required that I get some education.

First, I got a Raspberry Pi and started doing some tutorials in general programming.

Then I got some Pi Picos.

Then I got an Arduino Uno (rev 3). I kind of settled in on this micro controller to concentrate on more in-depth learning.

I learned of a thing called an Optical Digital Encoder, for transmitting the turns of the table crank to somewhere.

I learned about stepper motors and all that was involved with utilizing them.

I copied example code and tried to Frankenstein something to where the stepper would spin at some ratio to the encoder input. Of course this resulted in some failure and I even smoked a couple of boards. The best way to learn something is to figure out why it's not working. As of today, I think I've made a lot of progress in both C programming and properly understanding and assembling the electronic bits.

At this point, I have the ratio I needed for the specific cutting project, but it's hard coded. Now I want to expand on this "electronic transmission" and make it more generic so I can input the cutting angles I need from a user interface. At this moment I'm learning how to program LCD screens and accepting input from a keypad.

Here is my working proof-of-concept so far.

IMG_8642.jpeg
That tension spring works like crap. It doesn't keep the belt tight enough to even overcome the out-of-roundness from being shipped. Since then I ditched that and just tightened it by hand and tightened the clamps.

IMG_8654.jpeg
Strapping the motor to the table works out well. I can adjust it to take up the belt slack if I need to rotate the head back.

IMG_8692.jpeg
Missing: the pic of the power supply. I've switched from the original Arduino Uno to an Arduino Nano. Same pins and stuff, just smaller.

Here is my code so far:
/*
The encoder portion of this code is lifted from MoThunderz at https://github.com/mo-thunderz/RotaryEncoder.
I learned a lot from him.
*/
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
// Define rotary encoder pins
#define ENC_A 2
#define ENC_B 3
#define DirPin 6
#define PulsePin 7
#define StepsToTake 16 // This is the "factor" in determining the ratio of input to output
//for 0.33" in the x direction, the turntable will turn 90º giving me my 23º spiral
unsigned long _lastIncReadTime = micros();
unsigned long _lastDecReadTime = micros();
int _pauseLength = 25000;
int _fastIncrement = 10;
volatile int Direction = 0;
volatile int counter = 0;
LiquidCrystal_I2C lcd(0x27,20,4); //i2c addr, 20 chars, 4 lines
void setup() {
// Set encoder pins and attach interrupts
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(DirPin, OUTPUT);
pinMode(PulsePin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(ENC_A), read_encoder, HIGH);
attachInterrupt(digitalPinToInterrupt(ENC_B), read_encoder, HIGH);
// Start the serial monitor to show output
Serial.begin(115200);
lcd.init();
lcd.init(); //dunno why I have to do this twice
lcd.backlight();
}
void loop() {
static int lastCounter = 0;
// If count has changed print the new value to serial
if(counter != lastCounter){
Serial.println(counter);
lastCounter = counter;
}
lcd.setCursor(0,0);
lcd.print("Encoder: ");
lcd.setCursor(9,0);
lcd.print(counter);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("Stepper: ");
lcd.setCursor(9,1);
while (Serial.available() > 0) {
// display each character to the LCD
lcd.write(Serial.read()); //still working on how to get and display the number of turns the stepper is taking
}
lcd.print(counter);
lcd.print(" ");
}
void read_encoder() {
// Encoder interrupt routine for both pins. Updates counter
// if they are valid and have rotated a full indent
static uint8_t old_AB = 3; // Lookup table index
static int8_t encval = 0; // Encoder value
static const int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // Lookup table
old_AB <<=2; // Remember previous state
if (digitalRead(ENC_A)) old_AB |= 0x02; // Add current state of pin A
if (digitalRead(ENC_B)) old_AB |= 0x01; // Add current state of pin B

encval += enc_states[( old_AB & 0x0f )];
// Update counter if encoder has rotated a full indent, that is at least 4 steps
if( encval > 3 ) { // Four steps forward
Direction = 1;
int changevalue = 1;
if((micros() - _lastIncReadTime) < _pauseLength) {
// changevalue = _fastIncrement * changevalue;
}
_lastIncReadTime = micros();
counter = counter + changevalue; // Update counter
encval = 0;
sendPulseToStepper(Direction);
}
else if( encval < -3 ) { // Four steps backward
Direction = 0;
int changevalue = -1;
if((micros() - _lastDecReadTime) < _pauseLength) {
//changevalue = _fastIncrement * changevalue;
}
_lastDecReadTime = micros();
counter = counter + changevalue; // Update counter
encval = 0;
sendPulseToStepper(Direction);
}
}
void sendPulseToStepper(bool Direction){
digitalWrite(DirPin, Direction);
for (int x = 0; x < StepsToTake; x++){
digitalWrite(PulsePin, HIGH);
delayMicroseconds(10);
digitalWrite(PulsePin, LOW);
delayMicroseconds(10);
}
}

In my research into all this, I did run across electronic lead screws for lathes. That's a really similar situation to what I need. I actually ended up buying and implementing Clough42's Electronic Lead Screw for my lathe! However, C++ is definitely gibberish to me so no help (yet) in trying to implement his algorithms.

Anyway, I'm making incremental progress, but my old brain is resistant to accepting anything new, but I'm forcing it into submission with lots of coffee.

Any comments are welcome! I don't know what I don't know I don't know.
 
Last edited:
Nice work! I need to do something like that. What size stepper is that? NEMA 17? Not sure from the picture. I made my own ELS, there's a thread on it under DIY Electronics. Have you tried it out yet under load? Wondering about the holding torque.
 
I probably bought too much of a motor. I was really surprised by the amount of torque these guys put out and this motor can turn the rotary in its sleep. That's alright as I'd rather have that than having one that struggles. I got this motor and got the matching driver:
https://www.amazon.com/gp/product/B0781GNX8W/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
In my case I just made a plate with two holes to fasten it to the table and mounted the motor to the plate with this bracket:
https://www.amazon.com/gp/product/B073V77VLD/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

Thanks for the tip on the ELS thread! I'm off to check it out.
 
The drive arrangement you came up with for the rotary table is very clever! Nice work there.

Analyzing just about anyone else's code can be challenging, whether it's plain vanilla C or C++ so don't feel too bad about that.
 
You do want to use a decent amount of current for the stepper, because that's the current that is resisting the twist of the dividing head, which is caused by machining. Yes there's a worm gear too, but you want any movement to be solely due to your controller. So high levels of current (keeping thermals under control) are used to resist inadvertent stepper movement. Since, at first glance, you used an open loop stepper, you want to keep from losing any steps. If you use a closed loop stepper you have a little more margin.

Looks great so far!
 
I LOVE this! This is how I learn new things. It starts with something I want/need to accomplish, then I throw myself into it. I taught myself BASIC programming this way. It kept me interested and challenged for nearly 10 years. I started in on Visual Basic, but without an objective I lost interest quickly.
 
Back
Top