Coil Winding Machine

https://www.thingiverse.com/thing:4338142
Product: https://www.tindie.com/products/williambailes/plex-controller/

I’m will be making a new machine soon that will be able to do more with a better control system. Please send me a message here https://tinkersprojects.com/contact-me/ if you would like to help or get notified of any progress.

This is a coil winding machine to make it easier to wind coil around an object. I have been wanting to make one of these for a while and since there are some projects coming up with coils, I thought this was the best time.
The machine is a very simple design with 3D printed and laser-cut parts with aluminum extrusion as the basic frame. The coils get made using Nema17 motors, all controlled by the PLEX controller with Stepper motor drivers stacked on the Controller.

how the machine works

The machine is very simple, once the object is mounted, wire attached, turned on and homed, the user selects the parameters required and selects run. The machine will then start running. As the objects rotate, the Slide will go back and forth to evenly spread the wire.

This machine could be controlled with GCode but is currently not.

Code for Project

GNU General Public License v3.0

#include <Arduino.h>
#include <gcode.h>
#include <AccelStepper.h>
#include <LiquidCrystal.h>
#include <SimpleMenu.h>
#include <EEPROM.h>
#include <Plex.h>


#define EEPROM_SIZE 20

#define XMultiplier 48.2093663912 // number per 1mm
#define RMultiplier 400 // number per revilution

#define Speed 1000 //200
#define Acceleration 50000000.0

// inputs
#define UpPin 0
#define DownPin 1
#define BackPin 2
#define SelectPin 3
#define xLimitPin 4

// outputs
#define StepPinX 12
#define StepPinR 13
#define DirPin A5
#define XSelect 0
#define RSelect 3
#define enablePin A4

const float pi = 3.14159265359;
int XSpeed = 1000;
int DipSpeed = 1000;

AccelStepper stepperx(1,StepPinX,DirPin);
Plex PLEX;
AccelStepper stepperr(1,StepPinR,DirPin);













/****************************** CONTROL NOT USED YET ******************************/

void HomeMachine();
commandscallback commands[1] = {{"G28",HomeMachine}};
gcode Commands(1,commands);













/****************************** MENUS ******************************/
void About();
void RunProgram();
void SaveSettings();
int numberOfTurns = 100;
int width = 100;
int wireSpacing = 20;

SimpleMenu Menu[6] = {
  SimpleMenu("# of Turns",&numberOfTurns,0,1000),
  SimpleMenu("Width",&width,0,200),
  SimpleMenu("Wire Spacing",&wireSpacing),
  SimpleMenu("Run",RunProgram),
  SimpleMenu("Save",SaveSettings),
  SimpleMenu("About",About)
};

SimpleMenu TopMenu(6,Menu);

void display(SimpleMenu *_menu)
{
  PLEX.lcd.clear();
  PLEX.lcd.print(">");
  PLEX.lcd.print(_menu->name);

  SimpleMenu *next = TopMenu.next();
  if(next != NULL)
  {
    PLEX.lcd.setCursor(1,1);
    PLEX.lcd.print(next->name);
  }
}

void displayValue(SimpleMenu *_menu)
{
    PLEX.lcd.clear();
    PLEX.lcd.print(_menu->name);
    PLEX.lcd.setCursor(0,1);

    if(_menu == &Menu[1])
    {
        PLEX.lcd.print(_menu->getValue());
        PLEX.lcd.print(" mm");
    }
    else if(_menu == &Menu[2])
    {
        int decimalValue = _menu->getValue()%1000;
        int uppervalue = _menu->getValue()/1000;
        PLEX.lcd.print(uppervalue);
        PLEX.lcd.print(".");
        if(decimalValue<10)
        PLEX.lcd.print("0");
        if(decimalValue<100)
        PLEX.lcd.print("0");
        if(decimalValue<1)
        PLEX.lcd.print("0");
        PLEX.lcd.print(decimalValue);
        PLEX.lcd.print(" mm");
    }
    else
    {
        PLEX.lcd.print(_menu->getValue());
    }
    
}












/****************************** MAIN ******************************/
void setup()
{
    Commands.begin();
    
#ifndef __AVR__
    EEPROM.begin(EEPROM_SIZE);
#endif
/*
    pinMode(xLimitPin, INPUT);
    pinMode(UpPin, INPUT);
    pinMode(DownPin, INPUT);
    pinMode(BackPin, INPUT);
    pinMode(SelectPin, INPUT);*/
    pinMode(enablePin, OUTPUT);
    digitalWrite(enablePin,HIGH);

    PLEX.lcd.begin(16,2);
    
    stepperx.setMaxSpeed(Speed/10);
    stepperx.setSpeed(Speed/10);
    stepperx.setCurrentPosition(0);
    stepperx.setAcceleration(Acceleration);
    //stepperx.setPinsInverted(1,0,0); 
    
    stepperr.setMaxSpeed(Speed);
    stepperr.setSpeed(Speed);
    stepperr.setCurrentPosition(0);
    stepperr.setAcceleration(Acceleration);

    LoadData();
    About();  
    Enabled();
    HomeMachine();
    TopMenu.begin(display,displayValue);  
}

void loop() 
{
  if(digitalPressedDelay(UpPin))
  {
    TopMenu.up();
  }
  if(digitalPressedDelay(DownPin))
  {
    TopMenu.down();
  }
  if(digitalPressed(SelectPin))
  {
    TopMenu.select();
  }
  if(digitalPressed(BackPin))
  {
    TopMenu.back();
  }


  if(numberOfTurns<0)numberOfTurns=0;
  if(width<0)width=0;
  if(wireSpacing<0)wireSpacing=0;
}











/****************************** GUI ******************************/

void About()
{
  PLEX.lcd.clear();
  PLEX.lcd.print("Winding  Machine");
  PLEX.lcd.setCursor(0, 1);
  PLEX.lcd.print("Tinkers Projects");
  while(true)
  {
    delay(1);
    if(digitalPressed(SelectPin))
      break;
  }
}


void SaveSettings()
{
    SaveData();

    PLEX.lcd.clear();
    PLEX.lcd.print("     Saved!     ");
    while(true)
    {
        delay(1);
        if(digitalPressed(SelectPin))
        break;
    }

}


void RunProgram()
{
    HomeMachine();

    PLEX.lcd.clear();
    PLEX.lcd.print("Winding  ");
/*
    PLEX.lcd.setCursor(0, 1);
    PLEX.lcd.print("#: ");

/*
    int totalTurns = 0;
    double RealwireSpacing = wireSpacing/100;
    double turnsPreWidth = width/RealwireSpacing;
    double NumberOfLayers = numberOfTurns/turnsPreWidth;
*/
    long x = width*XMultiplier;
    long r = numberOfTurns*RMultiplier;
    stepperx.moveTo(x);
    stepperr.moveTo(r);

    double WidthSpeed = XMultiplier/RMultiplier*(((double)wireSpacing)/1000)*Speed;

    stepperx.setMaxSpeed(WidthSpeed);
    stepperx.setSpeed(WidthSpeed);
      /*  PLEX.lcd.setCursor(3, 1);
        PLEX.lcd.print(WidthSpeed);*/

    while(stepperr.distanceToGo() != 0)
    {
        /*if(digitalPressed(SelectPin))
            break;*/

        if(stepperx.distanceToGo() == 0)
        {
            if(stepperx.currentPosition() == 0)
            {
                stepperx.moveTo(x);
            }
            else
            {
                stepperx.moveTo(0);
            }
        }

        //PLEX.selectD(RSelect);
        stepperr.run();
        //PLEX.selectD(XSelect);
        stepperx.run();
/*
        int totalTurns = 10;//stepperr.currentPosition()/(RMultiplier);
        
        PLEX.lcd.setCursor(3, 1);
        PLEX.lcd.print(totalTurns);*/
        /*
        PLEX.lcd.print(stepperx.currentPosition());
        PLEX.lcd.print(" ");
        PLEX.lcd.print(stepperx.distanceToGo());
        PLEX.lcd.print("       ");

        
        int PercentDone = totalTurns/numberOfTurns;

        PLEX.lcd.setCursor(9, 0);
        PLEX.lcd.print(PercentDone);
        PLEX.lcd.print("%");

        */
    }

    PLEX.lcd.clear();
    PLEX.lcd.print("Finished");
    PLEX.lcd.setCursor(0, 1);
    PLEX.lcd.print("Cut/Remove Coil");



    

    while(true)
    {
        delay(1);
        if(digitalPressed(SelectPin))
        break;
    }

    HomeMachine();
}










/****************************** MACHINE CONTROL ******************************/

void Enabled()
{
  digitalWrite(enablePin,LOW);
}

void Disabled()
{
  digitalWrite(enablePin,HIGH);
}

void HomeMachine()
{
  PLEX.lcd.clear();
  PLEX.lcd.print("Homing");

    stepperx.setMaxSpeed(Speed/3);
    stepperx.setSpeed(Speed/3);

  PLEX.selectD(XSelect);
  while(PLEX.digitalReadC(xLimitPin) == LOW)
  {
    stepperx.move(-10);
    stepperx.run();
  }
  
  stepperx.setCurrentPosition(0);
  stepperr.setCurrentPosition(0);
}












/****************************** OTHER ******************************/

int pinStillPressed = -1;
int Currentdelay = 500;
bool digitalPressed(byte pin)
{
    bool ispressed = LOW;
    while(PLEX.digitalReadC(pin) == HIGH)
    {
        pinStillPressed = -1;
        Currentdelay = 500;
        ispressed = HIGH;
        delay(3);
    }
    return ispressed;
}

bool digitalPressedDelay(byte pin)
{
    bool ispressed = LOW;
    unsigned long timeStarted = millis();
    while(PLEX.digitalReadC(pin) == HIGH)
    {
        ispressed = HIGH;
        if(timeStarted+Currentdelay<millis())
        {
            pinStillPressed = pin;
            Currentdelay -= 50;
            break;
        }
    }

    if(pinStillPressed == pin && PLEX.digitalReadC(pinStillPressed) == LOW)
    {
        pinStillPressed = -1;
        Currentdelay = 500;
    }

    if(Currentdelay<5)
        Currentdelay = 5;

    return ispressed;
}

bool digitalPressed(byte pin, bool PreedValue)
{
    bool ispressed = LOW;
    while(PLEX.digitalReadC(pin) == PreedValue)
    {
        pinStillPressed = -1;
        Currentdelay = 500;
        ispressed = HIGH;
        delay(3);
    }
    return ispressed;
}





void SaveData()
{
    EEPROM.write(0,100);
    EEPROM.put(1, numberOfTurns);
    EEPROM.put(5, width);
    EEPROM.put(10, wireSpacing);
    
#ifndef __AVR__
    EEPROM.commit();
#endif
    
}

void LoadData()
{
    if(EEPROM.read(0) == 100)
    {
        EEPROM.get(1, numberOfTurns);
        EEPROM.get(5, width);
        EEPROM.get(10, wireSpacing);
    }
    
}

Related Projects

LCD-Simple-Menu Library

LCD-Simple-Menu Library

This is a simple LCD Menu Library for Arduino to make menus to control robots and machines. Menu Systems on an LCD has always been a thing that has gotten in the way of developing software for robots and machines. It always takes too long to implement and debug. sometimes most of the bugs are from the menu. This library is here to try and simplify the LCD menu but still giving control to …
Read more


G-Code-Arduino-Library

G-Code-Arduino-Library

This is a library that allows any machine or robot to be controlled by G-Code What is G-Code? G-Code is the instructions that 3D Printer and CNC used to create there part. G-Code is a set of instruction commands sent to the controller of the machine to be performed. Position, feed rate, and tool used are some of the items that G-Code can control. The G-Code can either be sent from the …
Read more


PLEX Controller

PLEX Controller

PLEX is a development board using the Arduino UNO bootloader to be easily programmed by the Arduino IDE. The board has many selectable analog inputs and digital output (up to 32, not including LCD interface). The board was originally designed for one project but has been used in many other projects that require a fast and simple solution. The PLEX board is the same dimensions as a 16×2 LCD …
Read more


Latest Projects

Popular Projects