Project showcase
Lathe - Electronic Lead Screw

Lathe - Electronic Lead Screw © LGPL

A servo-driven lead screw using Arduino to calculate proper spindle and lead screw speeds for cutting English and metric threads with VFD.

  • 7,667 views
  • 11 comments
  • 41 respects

Components and supplies

Necessary tools and machines

About this project

Background

This project began as a simple request, I wanted the ability to cut metric threads on my Atlas Craftsman lathe and eliminate the hassle of manually changing gears for the lead screw drive. After searching the web I could not find good information on making or buying an electronic lead screw so I decided to start make one. In addition, I decided to add a VFD to control the motor spindle speed.

Since the VFD driven spindle is a separate system to the electronic lead screw I broke it down into two parts: the spindle drive system and the lead screw drive system.

The spindle drive system is pretty straight forward. Replace the single-phase drive motor with a three-phase and drive it with a VFD.

The lead screw drive system uses an Arduino to create a sort of electronic gearbox. The Arduino reads the spindle speed and adjust the servo RPM to match the correct ratio based on user input to create either metric or English threads. An LCD display was used along with two momentary push buttons for the user interface. This allows the user to select either metric or English units and thread sizes. Once the desired thread or pitch is selected a 3-way switch is used to turn the motor in either CW or CCW direction. Once the motor is running the LCD does not update and you cannot change the thread pitch until the motor is stopped.

Spindle Drive System (VFD)

I decided purchase a 1/3hp 3ph motor and VFD kit from eBay, the motor frame size was similar to the existing 1/2hp 1ph motor so it was a direct fit.

For the drive system I also purchased an inline EMI filter (this TECO VFD puts off alot of noise and was interfering with the Arduino). The EMI filter was placed on the power supply side to the VFD.

Ferrite rings were used to reduce noise going from the VFD to the motor.

An on/off switch was used to provide power to the spindle and lead screw drive systems. This was mounted on the panel door.

The VFD can be used with an external potentiometer as well which is needed to control the motor speed while operating the lathe. The 10k pot works well. it was mounted on the Arduino enclosure.

These items were assembled into a nema 4 enclosure and wired together (I'm a mechanical guy, pay no attention to the birds nest of wire).

Lead Screw Drive System

A 24v 20 a power supply was used to provide power to the stepper motor (you could probably go with a lesser amperage P/S). The power supply was mounted in the VFD enclosure.

I decided to go with a NEMA 23 stepper motor with 3Nm of torque, If I could do it over again I would have stepped up to a NEMA 24, this motor has just enough power to cut threads without stalling.

A steel mounting bracket was used to mount the motor on the lathe work bench

A 14t 3/8in L timing pulley was used for the pinion drive on the stepper

For the timing pulley on the lead screw I used a 22t 3/8in L timing pulley with a taper lock adapter. The adaptor had a 0.75in bore with the same keyway that matched the existing lead screw. No modifications to the lathe were necessary.

Below is a picture of the stepper motor with the synchronous belt system. I cut out bottom of the safety door to fit over the stepper motor so it can be closed.

I used a microstepper driver to interface between the Arduino and the stepper motor. The driver uses the 24v power supply to pulse the stepper based on the signal from the Arduino. I simply mounted this on the underside of the bench near the stepper. I did not put it in the VFD panel since there was too much EMI.

To measure RPM of the spindle I used this inductive Hall effect sensor. Since it came with its own LCD I was able to use it to calibrate the Arduino speed calculation. I glued the magnet to the spindle as show below.

I used a small plastic case to house the LCD screen, Arduino, breadboard, and switches.

Plastic case

Arduino

LCD

Push buttons

3-way switch

The Code

The program has a few functions. The LiquidCrystal_I2C library and AccelStepper libraries were used. The screens are setup using an array so it is scalable. It uses the X variable to denote metric vs. English and the y variable prints each data field on the screen.

const int x = 2;
int currentX = 0;
String screens[x][5] = {{"TPI","Dir","LatheRPM ","ServoRPM","tpi/mm"}, {"Pitch","Dir","LatheRPM","ServoRPM","tpi/mm"}};

The set button flags loop uses a for loop to read the push button states and signal if a state has changed.

void setButtonFlags() 
{
 for(int i=0; i < n; i++)
 {
   buttonState[i] = digitalRead(buttonPin[i]);
   delay[1];
   if(buttonState[i] != lastButtonState[i])
   {
     if(buttonState[i] == HIGH)
     {
       //Serial.print("Button: ");
       //Serial.println(buttonPin[i]);
       buttonFlags[i] = HIGH;
     }
   }

The resolve button flags triggers a push button action if a button has changed state.

void resolveButtonFlags() 
{
 for(int i = 0; i < n; i++)
 {
   if(buttonFlags[i] == HIGH)
   {
     buttonAction(i);
     buttonFlags[i] = LOW;
     printScreen();
   }
 }
}

The button action loop determines what to do when a certain button is pressed while a certain screen is displayed. So when you are on the metric screen and you press button A the pitch will change. If you are in English the TPI will change.

void buttonAction(int button) 
{
 if (button == 0)
 {
   if (currentX == x-1)
   {
     currentX = 0;
   }
   else
   {
     currentX++;
   }
 }
 if (button == 1)
 {
   if (currentX == 0)
   {
     if(currentTPI == nTPI-1)
     {
       currentTPI = 0;
     }
     else
     {
       currentTPI++;
     }
   }

The speed sensor loop uses a debounce to trigger the calculate spindle RPM loop and stepper RPM loop. The stepper RPM will only change once per spindle revolution. Again, depending on which screen you are on it will either calculate English or metric.

void speedSensor() 
{
 time = millis();
 int currentSensorState = digitalRead(SensorPin);
 if (currentSensorState != lastSensorState)
 {
   lastDebounceTime = millis();
 }
 if ((millis() - lastDebounceTime) > debounceDelay)
 {
   if (currentSensorState != sensorState)
   {
     sensorState = currentSensorState;
     if (sensorState == LOW) 
     {
       calculateRPM(); // Real RPM from sensor
       if (currentX == 0)
       {
         englishCalc();
       }
       else if (currentX == 1)
       {
         metricCalc();
       }
     }
   }
 }

The send data loop operates while the stepper is not running and is used to send the information to the LCD screen. While the stepper is running this loop is not active since it slows down the processor of the arduino.

void sendData()
{
 unsigned long currentMillis = millis();
 if(currentMillis - prevMillis >= interval)
 {
   prevMillis = currentMillis;
   lcd.setCursor(9,2);
   lcd.println(lcdRPM);
   lcd.rightToLeft();
   lcd.print("   ");
   lcd.leftToRight();
   lcd.setCursor(9,3);
   lcd.println(servoRPM);
   lcd.rightToLeft();
   lcd.print("   ");
   lcd.leftToRight();
   lcdRPM = 0;
 }
}

The stepper speed calculations are based on the lead screw threads per inch ( in this case 8TPI), the synchronous belt gear ration ( in this case 1.529), the micro steps (in this case 400), and the RPM.

void metricCalc()
{
   stepperRPM = 1.529 * 0.315 * 400 * RPM * pitch[currentPitch] / 60.00;
   servoRPM = 0.482 * RPM * pitch[currentPitch];
}
// =========================== metric stepper speed =========================
void englishCalc()
{
   stepperRPM = 1.529 * 8.00 * 400.00 * RPM / ( tpi[currentTPI] * 60.00 );
   servoRPM = 1.529 * 8.00 * RPM / tpi[currentTPI];
}

Here is the main loop, once you get the stepper running only the speed sensor loop runs along with a stepper set speed library function and an if statement to stop the motor.

void loop()
{
 setButtonFlags();
 resolveButtonFlags();
 sendData();
 speedSensor();
 if (digitalRead(leftPin) == HIGH)
 {
   //direction = 1;
   lcd.setCursor(4,1);
   lcd.print("CW ");
   lcd.setCursor(9,3);
   lcd.println(servoRPM);
   lcd.rightToLeft();
   lcd.print("   ");
   lcd.leftToRight();
   lcd.setCursor(9,2);
   lcd.println(lcdRPM);
   lcd.rightToLeft();
   lcd.print("   ");
   lcd.leftToRight();
   delay(5);
   stepper.enableOutputs();
   stepper.setSpeed(stepperRPM);  
   stepper.run();
   while(stepper.isRunning())
   {
     speedSensor();
     stepper.setSpeed(stepperRPM);  
     stepper.run();
     if(digitalRead(leftPin)==LOW)
     {
       stepper.disableOutputs();
       lcd.setCursor(4,1);
       lcd.print("OFF");
       break;
     }
   }
 }
 else if (digitalRead(rightPin) == HIGH)
 {
   //direction = -1.00;
   lcd.setCursor(4,1);
   lcd.print("CCW");
   lcd.setCursor(9,3);
   lcd.println(servoRPM);
   lcd.rightToLeft();
   lcd.print("   ");
   lcd.leftToRight();
   lcd.setCursor(9,2);
   lcd.println(lcdRPM);
   lcd.rightToLeft();
   lcd.print("   ");
   lcd.leftToRight();
   delay(5);
   stepper.enableOutputs();
   stepper.setSpeed(-stepperRPM);  
   stepper.run();
   while(stepper.isRunning())
   {
     speedSensor();
     stepper.setSpeed(-1*stepperRPM);  
     stepper.run();
     if(digitalRead(rightPin)==LOW)
     {
       stepper.disableOutputs();
       lcd.setCursor(4,1);
       lcd.print("OFF");
       break;
     }
   }
 }
}

*Update*

I added an if statement so that while the program is in cutting/threading mode if you press and hold the blue momentary push button the spindle will run reverse in rapid mode for quick cutting of material.

if(digitalRead(buttonPin[1]) == HIGH)
     {
       stepper.setSpeed(1500);
       stepper.run();
     }

Conclusion

All in all the system works well. If you are cutting threads do not stop the servo motor as this will cause the spindle and lead screw to get out of time. You will not be able to retrace the same thread profile. If I had more time I would have put an encoder on the stepper motor to make a closed control loop so that the spindle and lead screw could be synchronized based on position as well. But this seems to work fine and I was able to cut metric threads with this setup as long as the servo stays running (just disengage the carriage like normal). Below you will find a list of components and basic description of each item to build the project along with schematics.

The wiring diagrams are attached along with the source code. You should be able to put it all these pieces together, upload the code and start cutting metal.

Thanks for reading!

Nick

Code

LeadScrewV2Arduino
With rapid mode
// included libraries
// liquid crystal l2c library and lcd function
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <AccelStepper.h>
AccelStepper stepper(AccelStepper::DRIVER,10,9);
// Speed sensor variables
const int SensorPin = 2;        // the number of the IR sensor input pin
int sensorState;                // the current state from the input pin
int lastSensorState = LOW;      // the previous InputState from the input pin
long lastDebounceTime = 0.00;   // the last time the output pin was toggled
long debounceDelay = 1.00;      // the debounce time; increase if the output flickers
long time;
long endTime;
long startTime;
volatile float RPM = 0.00;
float stepperRPM = 0.00;
float lnTime = 0.00;
int lcdRPM = 0;
int lastRPM = 0;

//button variables
const int n = 2;
const int buttonPin[n] = {3,4};
int buttonState[n] = {LOW,LOW};
int lastButtonState[n]= {LOW,LOW};
bool buttonFlags[n] = {LOW, LOW};

//three way switch variables
const int leftPin = 6;
const int rightPin = 5;

//screen variables
const int x = 2;
int currentX = 0;
int currentY = 0;
String screens[x][5] = {{"TPI","Dir","LatheRPM ","ServoRPM","tpi/mm"}, {"Pitch","Dir","LatheRPM","ServoRPM","tpi/mm"}};

//user input variables
const int nTPI = 18;
const int nPitch = 11;
int tpi[nTPI] = {256, 128, 64, 56, 48, 40, 32, 24, 20, 18, 16, 14, 13, 12, 11, 10, 9, 8};
int currentTPI = 0;
float pitch[nPitch]={0.40, 0.45, 0.50, 0.70, 0.70, 0.80, 1.00, 1.25, 1.50, 2.00, 2.50};
int currentPitch = 0;
//String dir[2] = {"CW ","CCW"};
//String currentDir = "CW";

//internal timer to send data
unsigned long prevMillis = 0;
const long interval = 1000;

//lathe parameters
float servoRPM = 0.00;
//int direction = 1;

// =========================== setup ===========================
void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.begin(20,4);
  Serial.begin(9600);
  for(int i=0; i < n; i++)
  {
    pinMode(buttonPin[i], INPUT);
    //Serial.print("Button: ");
    //Serial.println(buttonPin[i]);
  }
  pinMode(SensorPin, INPUT);
  endTime = 0;
  printScreen();
  // stepper stuff
  stepper.setEnablePin(8);
  stepper.disableOutputs();
  stepper.setMaxSpeed(2250);
  stepper.setAcceleration(300);
}
// =========================== main loop ===========================
void loop()
{
  setButtonFlags();
  resolveButtonFlags();
  sendData();
  speedSensor();
  if (digitalRead(leftPin) == HIGH)
  {
    //direction = 1;
    lcd.setCursor(4,1);
    lcd.print("CW ");
    lcd.setCursor(9,3);
    lcd.println(servoRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(9,2);
    lcd.println(lcdRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    delay(5);
    stepper.enableOutputs();
    stepper.setSpeed(stepperRPM);  
    stepper.run();
    while(stepper.isRunning())
    {
      speedSensor();
      stepper.setSpeed(stepperRPM);  
      stepper.run();
      if(digitalRead(buttonPin[1]) == HIGH)
      {
        stepper.setSpeed(-1500);
        stepper.run();
      }
      if(digitalRead(leftPin)==LOW)
      {
        stepper.disableOutputs();
        lcd.setCursor(4,1);
        lcd.print("OFF");
        break;
      }
    }
  }
  else if (digitalRead(rightPin) == HIGH)
  {
    //direction = -1.00;
    lcd.setCursor(4,1);
    lcd.print("CCW");
    lcd.setCursor(9,3);
    lcd.println(servoRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(9,2);
    lcd.println(lcdRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    delay(5);
    stepper.enableOutputs();
    stepper.setSpeed(-stepperRPM);  
    stepper.run();
    while(stepper.isRunning())
    {
      speedSensor();
      stepper.setSpeed(-1*stepperRPM);  
      stepper.run();
      if(digitalRead(buttonPin[1]) == HIGH)
      {
        stepper.setSpeed(1500);
        stepper.run();
      }
      if(digitalRead(rightPin)==LOW)
      {
        stepper.disableOutputs();
        lcd.setCursor(4,1);
        lcd.print("OFF");
        break;
      }
    }
  }
}
// =========================== set input flags ===========================
void setButtonFlags() 
{
  for(int i=0; i < n; i++)
  {
    buttonState[i] = digitalRead(buttonPin[i]);
    delay[1];
    if(buttonState[i] != lastButtonState[i])
    {
      if(buttonState[i] == HIGH)
      {
        //Serial.print("Button: ");
        //Serial.println(buttonPin[i]);
        buttonFlags[i] = HIGH;
      }
    }
    lastButtonState[i] = buttonState[i];
  }
}
// =========================== resolve button flags ===========================
void resolveButtonFlags() 
{
  for(int i = 0; i < n; i++)
  {
    if(buttonFlags[i] == HIGH)
    {
      buttonAction(i);
      buttonFlags[i] = LOW;
      printScreen();
    }
  }
}
// =========================== button action ===========================
void buttonAction(int button) 
{
  if (button == 0)
  {
    if (currentX == x-1)
    {
      currentX = 0;
    }
    else
    {
      currentX++;
    }
  }
  if (button == 1)
  {
    if (currentX == 0)
    {
      if(currentTPI == nTPI-1)
      {
        currentTPI = 0;
      }
      else
      {
        currentTPI++;
      }
    }
  else if (currentX == 1)
    {
      if(currentPitch == nPitch-1)
      {
        currentPitch = 0;
      }
      else
      {
        currentPitch++;
      }
    }
  }
}
// =========================== print screen ===========================
void printScreen() 
{
  lcd.clear();
  lcd.print(screens[currentX][0]);
  lcd.setCursor(0,1);
  lcd.print(screens[currentX][1]);
  lcd.setCursor(0,2);
  lcd.print(screens[currentX][2]);
  lcd.setCursor(0,3);
  lcd.print(screens[currentX][3]);
  lcd.setCursor(14,0);
  lcd.print(screens[currentX][4]);
  if(currentX == 0)
  {
    lcd.setCursor(4,0);    
    lcd.println(tpi[currentTPI]);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(4,1);
    lcd.print("OFF");
  }
  else if (currentX == 1)
  {
    lcd.setCursor(6,0);
    lcd.println(pitch[currentPitch]);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(4,1);
    lcd.print("OFF"); 
  }
}
// =========================== Speed Sensor loop ===========================
void speedSensor() 
{
  time = millis();
  int currentSensorState = digitalRead(SensorPin);

  if (currentSensorState != lastSensorState)
  {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay)
  {
    if (currentSensorState != sensorState)
    {
      sensorState = currentSensorState;
      if (sensorState == LOW) 
      {
        calculateRPM(); // Real RPM from sensor
        if (currentX == 0)
        {
          englishCalc();
        }
        else if (currentX == 1)
        {
          metricCalc();
        }
      }
    }
  }
  lastSensorState = currentSensorState;
  lcdRPM = RPM;
}

// =========================== RPM calculation ===========================
void calculateRPM()
{
  startTime = lastDebounceTime;
  lnTime = startTime - endTime;
  RPM = 60000.00 / (startTime - endTime);
  endTime = startTime;
}
// =========================== send speed data ===========================
void sendData()
{
  unsigned long currentMillis = millis();
  if(currentMillis - prevMillis >= interval)
  {
    prevMillis = currentMillis;
    lcd.setCursor(9,2);
    lcd.println(lcdRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(9,3);
    lcd.println(servoRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcdRPM = 0;
  }
}
// =========================== english stepper speed ===========================
void metricCalc()
{
    stepperRPM = 1.529 * 0.315 * 400 * RPM * pitch[currentPitch] / 60.00;
    servoRPM = 0.482 * RPM * pitch[currentPitch];
}
// =========================== metric stepper speed ===========================
void englishCalc()
{
    stepperRPM = 1.529 * 8.00 * 400.00 * RPM / ( tpi[currentTPI] * 60.00 );
    servoRPM = 1.529 * 8.00 * RPM / tpi[currentTPI];
}
leadScrewV1Arduino
// included libraries
// liquid crystal l2c library and lcd function
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <AccelStepper.h>
AccelStepper stepper(AccelStepper::DRIVER,10,9);
// Speed sensor variables
const int SensorPin = 2;        // the number of the IR sensor input pin
int sensorState;                // the current state from the input pin
int lastSensorState = LOW;      // the previous InputState from the input pin
long lastDebounceTime = 0.00;   // the last time the output pin was toggled
long debounceDelay = 5.00;      // the debounce time; increase if the output flickers
long time;
long endTime;
long startTime;
volatile float RPM = 0.00;
float stepperRPM = 0.00;
float lnTime = 0.00;
int lcdRPM = 0;
int lastRPM = 0;

//button variables
const int n = 2;
const int buttonPin[n] = {3,4};
int buttonState[n] = {LOW,LOW};
int lastButtonState[n]= {LOW,LOW};
bool buttonFlags[n] = {LOW, LOW};

//three way switch variables
const int leftPin = 6;
const int rightPin = 5;

//screen variables
const int x = 2;
int currentX = 0;
int currentY = 0;
String screens[x][5] = {{"TPI","Dir","LatheRPM ","ServoRPM","tpi/mm"}, {"Pitch","Dir","LatheRPM","ServoRPM","tpi/mm"}};

//user input variables
const int nTPI = 18;
const int nPitch = 11;
int tpi[nTPI] = {256, 128, 64, 56, 48, 40, 32, 24, 20, 18, 16, 14, 13, 12, 11, 10, 9, 8};
int currentTPI = 0;
float pitch[nPitch]={0.40, 0.45, 0.50, 0.70, 0.70, 0.80, 1.00, 1.25, 1.50, 2.00, 2.50};
int currentPitch = 0;
//String dir[2] = {"CW ","CCW"};
//String currentDir = "CW";

//internal timer to send data
unsigned long prevMillis = 0;
const long interval = 1000;

//lathe parameters
float servoRPM = 0.00;
//int direction = 1;

// =========================== setup ========================================
void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.begin(20,4);
  Serial.begin(9600);
  for(int i=0; i < n; i++)
  {
    pinMode(buttonPin[i], INPUT);
    //Serial.print("Button: ");
    //Serial.println(buttonPin[i]);
  }
  pinMode(SensorPin, INPUT);
  endTime = 0;
  printScreen();
  // stepper stuff
  stepper.setEnablePin(8);
  stepper.disableOutputs();
  stepper.setMaxSpeed(2502);
  stepper.setAcceleration(300);
}
// =========================== main loop ====================================
void loop()
{
  setButtonFlags();
  resolveButtonFlags();
  sendData();
  speedSensor();
  if (digitalRead(leftPin) == HIGH)
  {
    //direction = 1;
    lcd.setCursor(4,1);
    lcd.print("CW ");
    lcd.setCursor(9,3);
    lcd.println(servoRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(9,2);
    lcd.println(lcdRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    delay(5);
    stepper.enableOutputs();
    stepper.setSpeed(stepperRPM);  
    stepper.run();
    while(stepper.isRunning())
    {
      speedSensor();
      stepper.setSpeed(stepperRPM);  
      stepper.run();
      if(digitalRead(leftPin)==LOW)
      {
        stepper.disableOutputs();
        lcd.setCursor(4,1);
        lcd.print("OFF");
        break;
      }
    }
  }
  else if (digitalRead(rightPin) == HIGH)
  {
    //direction = -1.00;
    lcd.setCursor(4,1);
    lcd.print("CCW");
    lcd.setCursor(9,3);
    lcd.println(servoRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(9,2);
    lcd.println(lcdRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    delay(5);
    stepper.enableOutputs();
    stepper.setSpeed(-stepperRPM);  
    stepper.run();
    while(stepper.isRunning())
    {
      speedSensor();
      stepper.setSpeed(-1*stepperRPM);  
      stepper.run();
      if(digitalRead(rightPin)==LOW)
      {
        stepper.disableOutputs();
        lcd.setCursor(4,1);
        lcd.print("OFF");
        break;
      }
    }
  }
}
// =========================== set input flags ===========================
void setButtonFlags() 
{
  for(int i=0; i < n; i++)
  {
    buttonState[i] = digitalRead(buttonPin[i]);
    delay[1];
    if(buttonState[i] != lastButtonState[i])
    {
      if(buttonState[i] == HIGH)
      {
        //Serial.print("Button: ");
        //Serial.println(buttonPin[i]);
        buttonFlags[i] = HIGH;
      }
    }
    lastButtonState[i] = buttonState[i];
  }
}
// =========================== resolve button flags =========================
void resolveButtonFlags() 
{
  for(int i = 0; i < n; i++)
  {
    if(buttonFlags[i] == HIGH)
    {
      buttonAction(i);
      buttonFlags[i] = LOW;
      printScreen();
    }
  }
}
// =========================== button action ===============================
void buttonAction(int button) 
{
  if (button == 0)
  {
    if (currentX == x-1)
    {
      currentX = 0;
    }
    else
    {
      currentX++;
    }
  }
  if (button == 1)
  {
    if (currentX == 0)
    {
      if(currentTPI == nTPI-1)
      {
        currentTPI = 0;
      }
      else
      {
        currentTPI++;
      }
    }
  else if (currentX == 1)
    {
      if(currentPitch == nPitch-1)
      {
        currentPitch = 0;
      }
      else
      {
        currentPitch++;
      }
    }
  }
}
// =========================== print screen ===========================
void printScreen() 
{
  lcd.clear();
  lcd.print(screens[currentX][0]);
  lcd.setCursor(0,1);
  lcd.print(screens[currentX][1]);
  lcd.setCursor(0,2);
  lcd.print(screens[currentX][2]);
  lcd.setCursor(0,3);
  lcd.print(screens[currentX][3]);
  lcd.setCursor(14,0);
  lcd.print(screens[currentX][4]);
  if(currentX == 0)
  {
    lcd.setCursor(4,0);    
    lcd.println(tpi[currentTPI]);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(4,1);
    lcd.print("OFF");
  }
  else if (currentX == 1)
  {
    lcd.setCursor(6,0);
    lcd.println(pitch[currentPitch]);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(4,1);
    lcd.print("OFF"); 
  }
}
// =========================== Speed Sensor loop ===========================
void speedSensor() 
{
  time = millis();
  int currentSensorState = digitalRead(SensorPin);

  if (currentSensorState != lastSensorState)
  {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay)
  {
    if (currentSensorState != sensorState)
    {
      sensorState = currentSensorState;
      if (sensorState == LOW) 
      {
        calculateRPM(); // Real RPM from sensor
        if (currentX == 0)
        {
          englishCalc();
        }
        else if (currentX == 1)
        {
          metricCalc();
        }
      }
    }
  }
  lastSensorState = currentSensorState;
  lcdRPM = RPM;
}

// =========================== RPM calculation ===========================
void calculateRPM()
{
  startTime = lastDebounceTime;
  lnTime = startTime - endTime;
  RPM = 60000.00 / (startTime - endTime);
  endTime = startTime;
}
// =========================== send speed data ===========================
void sendData()
{
  unsigned long currentMillis = millis();
  if(currentMillis - prevMillis >= interval)
  {
    prevMillis = currentMillis;
    lcd.setCursor(9,2);
    lcd.println(lcdRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcd.setCursor(9,3);
    lcd.println(servoRPM);
    lcd.rightToLeft();
    lcd.print("   ");
    lcd.leftToRight();
    lcdRPM = 0;
  }
}
// =========================== english stepper speed ========================
void metricCalc()
{
    stepperRPM = 1.529 * 0.315 * 400 * RPM * pitch[currentPitch] / 60.00;
    servoRPM = 0.482 * RPM * pitch[currentPitch];
}
// =========================== metric stepper speed =========================
void englishCalc()
{
    stepperRPM = 1.529 * 8.00 * 400.00 * RPM / ( tpi[currentTPI] * 60.00 );
    servoRPM = 1.529 * 8.00 * RPM / tpi[currentTPI];
}

Schematics

Servo Controller Schematic
Leadscrewschematic ad5gijqzdu
Spindle VFD Schematic
Vfdimage cdnm9db6ng

Comments

Similar projects you might like

Electronic Music

Project showcase by Glauber Santiago

  • 1,092 views
  • 1 comment
  • 0 respects

Regina - Electronic Version

Project showcase by pmrleite

  • 777 views
  • 0 comments
  • 0 respects

Electronic Safe with Arduino

Project showcase by chummer1010

  • 28,869 views
  • 30 comments
  • 60 respects

Electronic Check-In

Project tutorial by Gergely Imreh

  • 5,713 views
  • 9 comments
  • 30 respects

New Electronic Music Instrument Design

Project showcase by cpeckmusic

  • 5,335 views
  • 0 comments
  • 22 respects

Electronic Chessboard (4x4 Demo Prototype)

Project tutorial by Tahir Miriyev

  • 1,198 views
  • 6 comments
  • 7 respects
Add projectSign up / Login