Teensy 3.2 Tesla Coil Winder

Status
Not open for further replies.

jparisse

Active member
I am rewriting Jeff Rosowski's Arduino code to run on the Teensy. This version works on the Teensy 3.2 but I am sure much can be done to clean up the code.

If there is a better way to post or attach the code, please let me know.

Jeff


Code:
/*  v1.0 Tesla Coil Winder Firmware                 */
/*  29 Jan 2014 - Jeff Rosowski                     */
/*  [url]https://github.com/krux702/tesla_coil_winder[/url]    */
/*  v 1.1 for Teensy 3.2   (20ms step pulse)        */
/*  12 Dec 2017 - Jeff Parisse                      */

#include <Wire.h>
#include <Adafruit_LiquidCrystal.h>
#include <avr/eeprom.h>
#include <MenuSystem.h>
#include <stdlib.h>

#define BAUDRATE 19200

//                  "                   "
#define MENU_TITLE  "Tesla Winder v1.1  "
#define MANUAL      "Manual Control     "
#define ENABLE      "Stepper Enable     "
#define JOG_COIL    "Jog coil           "
#define JOG_GUIDE   "Jog guide          "
#define SETTINGS    "Settings           "
#define COIL_STEPS  "Coil steps/rot     "
#define COIL_INV    "Coil invert        "
#define GUIDE_STEPS "Guide steps/mm     "
#define GUIDE_INV   "Guide invert       "
#define HOME        "Home guide         "
#define SETUP_JOB   "Setup Job          "
#define SETUP_HELP  "Size in micrometers"
#define WIRE_SIZE   "Wire size          "
#define COIL_DIAM   "Coil diam          "
#define COIL_HOME   "Home offset        "
#define COIL_CALC   "Calc coil size     "
#define COIL_RATIO  "Coil ratio         "
#define COIL_LEN    "Coil len           "
#define COIL_TURNS  "Coil turns         "
#define COIL_SPEED  "Speed mm/sec       "
#define START       "Start              "

MenuSystem ms;
Menu mm(MENU_TITLE);
Menu manual(MANUAL);
MenuItem manual_stepper(ENABLE);
MenuItem manual_jogcoil(JOG_COIL);
MenuItem manual_jogguide(JOG_GUIDE);
Menu settings(SETTINGS);
MenuItem settings_coilsteps(COIL_STEPS);
MenuItem settings_coilinvert(COIL_INV);
MenuItem settings_guidesteps(GUIDE_STEPS);
MenuItem settings_guideinvert(GUIDE_INV);
MenuItem settings_coilhome(COIL_HOME);
MenuItem settings_home(HOME);
Menu job(SETUP_JOB);
MenuItem job_help(SETUP_HELP);
MenuItem job_wiredia(WIRE_SIZE);
MenuItem job_coildia(COIL_DIAM);
MenuItem job_coilhome(COIL_HOME);
MenuItem job_coilcalc(COIL_CALC);
MenuItem job_coilratio(COIL_RATIO);
MenuItem job_length(COIL_LEN);
MenuItem job_turns(COIL_TURNS);
MenuItem job_speed(COIL_SPEED);
MenuItem job_home(HOME);
MenuItem job_start(START);

const int min_stop = 17;
const int max_stop = 16;

const int led = 13;
byte line = 0;
byte cursor_line = 0;

// stepper a - guide
const int stepper_a_enable = 12;
const int stepper_a_direction = 11;
const int stepper_a_step = 10;
long stepper_a_steps = 0;
byte stepper_a_run = 0;
byte stepper_a_dir = 0;
byte stepper_a_ena = 0;

// stepper b - coil
const int stepper_b_enable = 7;
const int stepper_b_direction = 8;
const int stepper_b_step = 9;
long stepper_b_steps = 0;
byte stepper_b_run = 0;
byte stepper_b_dir = 0;
byte stepper_b_ena = 0;

// input buttons
const int button_a = 2;  // ENTER
const int button_b = 3;  // DOWN
const int button_c = 4;  // UP
const int button_d = 5;  // LEFT
const int button_e = 6;  // RIGHT
const int invert_buttons = 1;    // invert buttons

// switch debounce
#define DEBOUNCE_TIME 10    // Default 20
#define LONG_TIME 250       // Default 500
long a_wait_timer;
long b_wait_timer;
long c_wait_timer;
long d_wait_timer;
long e_wait_timer;
long a_wait_timer2;
long b_wait_timer2;
long c_wait_timer2;
long d_wait_timer2;
long e_wait_timer2;
byte min_state;
byte max_state;
byte a_state;
byte b_state;
byte c_state;
byte d_state;
byte e_state;
byte a_state2;
byte b_state2;
byte c_state2;
byte d_state2;
byte e_state2;
bool a_state_ack;
bool b_state_ack;
bool c_state_ack;
bool d_state_ack;
bool e_state_ack;
bool a_state_ack2;
bool b_state_ack2;
bool c_state_ack2;
bool d_state_ack2;
bool e_state_ack2;

// stepper acceleration
long current_delay = 2000;
long current_step = 0;

// configuration values
struct config_t
{
  unsigned long coilSteps;
  bool coilInvert;
  unsigned long guideSteps;
  bool guideInvert;
  unsigned long wireSize;   // micrometers
  unsigned long coilDiam;   // micrometers
  unsigned long coilLength; // micrometers
  unsigned long coilTurns;
  unsigned long coilSpeed;
  bool coilCalc;
  float coilRatio;
  unsigned long coilHome;   // micrometers
} conf;

// Connect via i2c, default address #0 (A0-A2 not jumpered)
Adafruit_LiquidCrystal lcd(0);


void setup()
{
  Serial.begin(BAUDRATE);

  pinMode(min_stop, INPUT);           // set pin to input
  digitalWrite(min_stop, HIGH);       // turn on pullup resistors
  pinMode(max_stop, INPUT);           // set pin to input
  digitalWrite(max_stop, HIGH);       // turn on pullup resistors

  pinMode(led, OUTPUT);               // set pin to output

  pinMode(button_a, INPUT);           // set pin to input
  digitalWrite(button_a, HIGH);       // turn on pullup resistors
  pinMode(button_b, INPUT);           // set pin to input
  digitalWrite(button_b, HIGH);       // turn on pullup resistors
  pinMode(button_c, INPUT);           // set pin to input
  digitalWrite(button_c, HIGH);       // turn on pullup resistors
  pinMode(button_d, INPUT);           // set pin to input
  digitalWrite(button_d, HIGH);       // turn on pullup resistors
  pinMode(button_e, INPUT);           // set pin to input
  digitalWrite(button_e, HIGH);       // turn on pullup resistors

  pinMode(stepper_a_enable, OUTPUT);
  pinMode(stepper_a_direction, OUTPUT);
  pinMode(stepper_a_step, OUTPUT);
  pinMode(stepper_b_enable, OUTPUT);
  pinMode(stepper_b_direction, OUTPUT);
  pinMode(stepper_b_step, OUTPUT);

  digitalWrite(stepper_a_enable, HIGH);      // HIGH = disabled
  digitalWrite(stepper_a_direction, HIGH);  // HIGH = forward
  digitalWrite(stepper_a_step, LOW);

  digitalWrite(stepper_b_enable, HIGH);      // HIGH = disabled
  digitalWrite(stepper_b_direction, HIGH);  // HIGH = forward
  digitalWrite(stepper_b_step, LOW);


  // set up the LCD's number of rows and columns:
  lcd.begin(20, 4);

  // define menu structure
  mm.add_menu(&manual);
  manual.add_item(&manual_stepper, &menu_stepper_enable);
  manual.add_item(&manual_jogcoil, &menu_jog_coil);
  manual.add_item(&manual_jogguide, &menu_jog_guide);

  mm.add_menu(&settings);
  settings.add_item(&settings_coilsteps, &menu_settings_coilsteps);
  settings.add_item(&settings_coilinvert, &menu_settings_coilinvert);
  settings.add_item(&settings_guidesteps, &menu_settings_guidesteps);
  settings.add_item(&settings_guideinvert, &menu_settings_guideinvert);
  settings.add_item(&settings_coilhome, &menu_job_coilhome);
  settings.add_item(&settings_home, &menu_home_guide);

  mm.add_menu(&job);
  job.add_item(&job_help, &menu_job_help);
  job.add_item(&job_wiredia, &menu_job_wiredia);
  job.add_item(&job_coildia, &menu_job_coildia);
  job.add_item(&job_coilhome, &menu_job_coilhome);
  job.add_item(&job_coilcalc, &menu_job_calc);
  job.add_item(&job_coilratio, &menu_job_ratio);
  job.add_item(&job_length, &menu_job_length);
  job.add_item(&job_turns, &menu_job_turns);
  job.add_item(&job_speed, &menu_job_speed);
  job.add_item(&job_home, &menu_home_guide);
  job.add_item(&job_start, &menu_job_start);

  mm.add_item(&job_start, &menu_job_start);

  ms.set_root_menu(&mm);

  lcd.setBacklight(LOW);
  delay(100);
  lcd.setBacklight(HIGH);

  // Print a message to the lcd.
  lcd.clear();

  String LCDScroll = "                   Project Icarus      ";
  for (int i = 0 ; i < 20 ; i++)
  {
    lcd.setCursor(0, 0);
    lcd.print(LCDScroll.substring(i, i + 20));
    delay(75);
  }

  // read eeprom settings
  eeprom_read_block((void*)&conf, (void*)0, sizeof(conf));

  // set to initial sane values and save
  conf.coilSteps = 6400;    // 400 steps/rev * 16th steps
  conf.coilInvert = 1;
  conf.guideSteps = 800;    // 400 steps/rev * 16th steps
  conf.guideInvert = 1;
  conf.wireSize = 141;      // micrometers
  conf.coilDiam = 108712;   // micrometers
  conf.coilLength = 228600; // micrometers
  conf.coilTurns = 814;
  conf.coilSpeed = 100;
  conf.coilCalc = 1;
  conf.coilRatio = 5.00;
  conf.coilHome = 7000;    // micrometers

  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));

  delay(1500);

  lcd.clear();
  delay(160);
  displayMenu();
}


void loop()
{
  check_buttons();

  if (a_state && !a_state_ack)
  {
    // center
    a_state_ack = 1;
    ms.select(0);
    displayMenu();
  }
  if (b_state && !b_state_ack)
  {
    // down
    b_state_ack = 1;
    ms.next();
    displayMenu();
  }
  if (c_state && !c_state_ack)
  {
    // up
    c_state_ack = 1;
    ms.prev();
    displayMenu();
  }
  if (d_state && !d_state_ack)
  {
    // left
    d_state_ack = 1;
    ms.back();
    displayMenu();
  }
  delay(10);               // wait Default 1000
}

void check_buttons()
{
  // end stop code
  min_state = digitalRead(min_stop);
  max_state = digitalRead(max_stop);

  // button debounce code

  int a_read = invert_buttons ^ digitalRead(button_a);
  if (a_read == a_state)
  {
    a_wait_timer = millis();
  }
  else if (a_read != a_state and (millis() - a_wait_timer) > DEBOUNCE_TIME)
  {
    a_state = a_read;
    a_state_ack = 0;
  }

  if (a_read == a_state2)
  {
    a_wait_timer2 = millis();
  }
  else if (a_read != a_state2 and (millis() - a_wait_timer2) > LONG_TIME)
  {
    a_state2 = a_read;
    a_state_ack2 = 0;
  }

  int b_read = invert_buttons ^ digitalRead(button_b);
  if (b_read == b_state)
  {
    b_wait_timer = millis();
  }
  else if (b_read != b_state and (millis() - b_wait_timer) > DEBOUNCE_TIME)
  {
    b_state = b_read;
    b_state_ack = 0;
  }

  if (b_read == b_state2)
  {
    b_wait_timer2 = millis();
  }
  else if (b_read != b_state2 and (millis() - b_wait_timer2) > LONG_TIME)
  {
    b_state2 = b_read;
    b_state_ack2 = 0;
  }

  int c_read = invert_buttons ^ digitalRead(button_c);
  if (c_read == c_state)
  {
    c_wait_timer = millis();
  }
  else if (c_read != c_state and (millis() - c_wait_timer) > DEBOUNCE_TIME)
  {
    c_state = c_read;
    c_state_ack = 0;
  }

  if (c_read == c_state2)
  {
    c_wait_timer2 = millis();
  }
  else if (c_read != c_state2 and (millis() - c_wait_timer2) > LONG_TIME)
  {
    c_state2 = c_read;
    c_state_ack2 = 0;
  }

  int d_read = invert_buttons ^ digitalRead(button_d);
  if (d_read == d_state)
  {
    d_wait_timer = millis();
  }
  else if (d_read != d_state and (millis() - d_wait_timer) > DEBOUNCE_TIME)
  {
    d_state = d_read;
    d_state_ack = 0;
  }

  int e_read = invert_buttons ^ digitalRead(button_e);
  if (e_read == e_state)
  {
    e_wait_timer = millis();
  }
  else if (e_read != e_state and (millis() - e_wait_timer) > DEBOUNCE_TIME)
  {
    e_state = e_read;
    e_state_ack = 0;
  }
}

void menu_stepper_enable(MenuItem* p_menu_item)
{
  stepper_enable(1 ^ (stepper_a_ena & 1));
}

void stepper_enable(byte enable)
{
  /*
    options
    0 = turn off and save
    1 = turn on and save
    3 = turn off
    4 = turn on
    5 = revert to saved

    bits
    1 = operating state
    2 = saved state

    Set bit
    number |= 1 << x;

    Clear bit
    number &= ~(1 << x);

    Toggle bit
    number ^= 1 << x;

    Check bit
    bit = number & (1 << x);
  */
  if (enable == 0)
  {
    // set and save bit 1 and 2
    stepper_a_ena = 0;
  }
  else if (enable == 1)
  {
    stepper_a_ena = 3;
  }
  else if (enable == 3)
  {
    // turn off 1 bit
    stepper_a_ena &= ~(1 << 0);
  }
  else if (enable == 4)
  {
    // turn on 1 bit
    stepper_a_ena |= 1 << 0;
  }
  else if (enable == 5)
  {
    byte stepper_saved = stepper_a_ena & 2;
    if (stepper_saved)
    {
      stepper_a_ena |= 1 << 0;
    }
    else
    {
      stepper_a_ena &= ~(1 << 0);
    }
  }

  if (stepper_a_ena & 1)
  {
    // enable steppers
    digitalWrite(led, HIGH);
    digitalWrite(stepper_a_enable, LOW);      // HIGH = disabled
    digitalWrite(stepper_b_enable, LOW);      // HIGH = disabled
  }
  else if (!stepper_a_ena & 1)
  {
    // disable steppers
    digitalWrite(led, LOW);
    digitalWrite(stepper_a_enable, HIGH);      // HIGH = disabled
    digitalWrite(stepper_b_enable, HIGH);      // HIGH = disabled
  }
}


void displayMenu()
{
  lcd.setCursor(0, 0);
  // Display the menu
  Menu const* cp_menu = ms.get_current_menu();

  //lcd.print("Current menu name: ");
  lcd.print(cp_menu->get_name());

  lcd.setCursor(0, 1);

  MenuComponent const* cp_menu_sel = cp_menu->get_selected();

  int menu_components = cp_menu->get_num_menu_components();
  int current_item = cp_menu->get_cur_menu_component_num();

  // calculate start and end items
  int start = current_item - 1;
  if (start < 0)
  {
    start = 0;
  }
  if (start + 3 > menu_components)
  {
    start = menu_components - 3;
  }
  int max_item = start + 3;
  if (max_item > menu_components)
  {
    max_item = menu_components;
  }

  line = 1;
  for (int i = start; i < max_item; ++i)
  {
    lcd.setCursor(0, line);

    MenuComponent const* cp_m_comp = cp_menu->get_menu_component(i);

    if (cp_menu_sel == cp_m_comp)
    {
      lcd.print(">");
      cursor_line = line;
    }
    else
    {
      lcd.print(" ");
    }

    lcd.print(cp_m_comp->get_name());


    // display setting information
    if (cp_m_comp->get_name() == ENABLE)
    {
      print_bool(stepper_a_ena & 1);
    }
    else if (cp_m_comp->get_name() == COIL_STEPS)
    {
      print_long(conf.coilSteps);
    }
    else if (cp_m_comp->get_name() == COIL_INV)
    {
      print_bool(conf.coilInvert);
    }
    else if (cp_m_comp->get_name() == GUIDE_INV)
    {
      print_bool(conf.guideInvert);
    }
    else if (cp_m_comp->get_name() == GUIDE_STEPS)
    {
      print_long(conf.guideSteps);
    }
    else if (cp_m_comp->get_name() == WIRE_SIZE)
    {
      print_long(conf.wireSize);
    }
    else if (cp_m_comp->get_name() == COIL_DIAM)
    {
      print_long(conf.coilDiam);
    }
    else if (cp_m_comp->get_name() == COIL_HOME)
    {
      print_long(conf.coilHome);
    }
    else if (cp_m_comp->get_name() == COIL_CALC)
    {
      print_bool(conf.coilCalc);
    }
    else if (cp_m_comp->get_name() == COIL_RATIO)
    {
      print_float(conf.coilRatio);
    }
    else if (cp_m_comp->get_name() == COIL_LEN)
    {
      print_long(conf.coilLength);
    }
    else if (cp_m_comp->get_name() == COIL_TURNS)
    {
      print_long(conf.coilTurns);
    }
    else if (cp_m_comp->get_name() == COIL_SPEED)
    {
      print_long(conf.coilSpeed);
    }

    line++;
  }
}

void print_bool(bool bool_val)
{
  lcd.setCursor(17, line);
  if (bool_val)
  {
    lcd.print("Yes");
  }
  else
  {
    lcd.print(" No");
  }
}

void print_long(long long_val)
{
  char buf[16];

  ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr

  lcd.setCursor(20 - strlen(buf), line);
  lcd.print(buf);
}

void print_float(float float_val)
{
  char buf[16];

  //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
  dtostrf(float_val, 4, 2, buf);

  lcd.setCursor(20 - strlen(buf), line);
  lcd.print(buf);
}

long edit_long(long long_val)
{
  long incr = 1;
  byte incr_count = 0;
  long saved_long_val = long_val;
  char buf[16];
  line = cursor_line;

  ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr

  lcd.setCursor(0, line);
  lcd.print(" ");

  lcd.setCursor(18 - strlen(buf), cursor_line);
  lcd.print(" >");

  while (1)
  {
    check_buttons();

    if (a_state && !a_state_ack)
    {
      // center
      a_state_ack = 1;
      break;
    }
    if (b_state2 && !b_state_ack2)
    {
      incr_count++;
      if (incr_count > 8)
      {
        incr = incr * 10;
        incr_count = 0;
      }

      if (long_val > incr)
      {
        long_val = long_val - incr;
      }
      else
      {
        ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
        lcd.setCursor(19 - strlen(buf), cursor_line);
        for (int i = 0; i <= strlen(buf); i++)
        {
          lcd.print(" ");
        }
        long_val = 0;
      }

      b_state2 = 0;
      b_state_ack2 = 1;

      b_wait_timer2 = millis();

      ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_long(long_val);
    }
    if (b_state == 2 && !b_state_ack)
    {
      if (long_val > 10)
      {
        long_val = long_val - 10;
      }
      else
      {
        ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
        lcd.setCursor(19 - strlen(buf), cursor_line);
        for (int i = 0; i <= strlen(buf); i++)
        {
          lcd.print(" ");
        }
        long_val = 0;
      }
      b_state_ack = 1;

      ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_long(long_val);
    }
    if (b_state && !b_state_ack)
    {
      // down
      if (long_val > 0)
      {
        long_val--;
      }
      b_state_ack = 1;

      incr = 1;
      incr_count = 0;

      ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_long(long_val);
    }
    if (c_state2 && !c_state_ack2)
    {
      incr_count++;
      if (incr_count > 8)
      {
        incr = incr * 10;
        incr_count = 0;
      }
      long_val = long_val + incr;
      c_state2 = 0;
      c_state_ack2 = 1;

      c_wait_timer2 = millis();

      ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_long(long_val);
    }
    if (c_state && !c_state_ack)
    {
      // up
      long_val++;
      c_state_ack = 1;
      incr = 1;
      incr_count = 0;

      ltoa(long_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_long(long_val);
    }
    if (d_state && !d_state_ack)
    {
      // left
      d_state_ack = 1;
      long_val = saved_long_val;
      break;
    }
  }

  return long_val;
}

float edit_float(float float_val)
{
  float incr = .01;
  byte incr_count = 0;
  float saved_float_val = float_val;
  char buf[16];
  line = cursor_line;

  // ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
  dtostrf(float_val, 4, 2, buf);

  lcd.setCursor(0, line);
  lcd.print(" ");

  lcd.setCursor(18 - strlen(buf), cursor_line);
  lcd.print(" >");

  while (1)
  {
    check_buttons();

    if (a_state && !a_state_ack)
    {
      // center
      a_state_ack = 1;
      break;
    }
    if (b_state2 && !b_state_ack2)
    {
      incr_count++;
      if (incr_count > 8)
      {
        incr = incr * 10;
        incr_count = 0;
      }

      if (float_val > incr)
      {
        float_val = float_val - incr;
      }
      else
      {
        //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
        dtostrf(float_val, 4, 2, buf);

        lcd.setCursor(19 - strlen(buf), cursor_line);
        for (int i = 0; i <= strlen(buf); i++)
        {
          lcd.print(" ");
        }
        float_val = 0;
      }

      b_state2 = 0;
      b_state_ack2 = 1;

      b_wait_timer2 = millis();

      //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      dtostrf(float_val, 4, 2, buf);

      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_float(float_val);
    }
    if (b_state == 2 && !b_state_ack)
    {
      if (float_val > 10)
      {
        float_val = float_val - 10;
      }
      else
      {
        //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
        dtostrf(float_val, 4, 2, buf);

        lcd.setCursor(19 - strlen(buf), cursor_line);
        for (int i = 0; i <= strlen(buf); i++)
        {
          lcd.print(" ");
        }
        float_val = 0;
      }
      b_state_ack = 1;

      //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      dtostrf(float_val, 4, 2, buf);

      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_float(float_val);
    }
    if (b_state && !b_state_ack)
    {
      // down
      incr = .01;
      incr_count = 0;

      if (float_val > 0)
      {
        float_val = float_val - incr;
      }
      b_state_ack = 1;

      //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      dtostrf(float_val, 4, 2, buf);

      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_float(float_val);
    }
    if (c_state2 && !c_state_ack2)
    {
      incr_count++;
      if (incr_count > 8)
      {
        incr = incr * 10;
        incr_count = 0;
      }
      float_val = float_val + incr;
      c_state2 = 0;
      c_state_ack2 = 1;

      c_wait_timer2 = millis();

      //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      dtostrf(float_val, 4, 2, buf);

      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_float(float_val);
    }
    if (c_state && !c_state_ack)
    {
      // up
      c_state_ack = 1;
      incr = .01;
      incr_count = 0;
      float_val = float_val + incr;

      //ltoa(float_val, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
      dtostrf(float_val, 4, 2, buf);

      lcd.setCursor(18 - strlen(buf), cursor_line);
      lcd.print(" >");
      print_float(float_val);
    }
    if (d_state && !d_state_ack)
    {
      // left
      d_state_ack = 1;
      float_val = saved_float_val;
      break;
    }
  }

  return float_val;
}

void delay_step(long steps, int max_delay_time, int delay_time, int step_amount, byte accel_mode)
{
  long accel_steps = (max_delay_time - delay_time) / step_amount;
  accel_steps = abs(accel_steps);

  if (current_step == 0)
  {
    current_delay = max_delay_time;
  }
  else if (current_step > (steps - accel_steps) and accel_mode & 1)
  {
    // decel
    if (current_delay < max_delay_time)
    {
      current_delay = current_delay + step_amount;
    }
  }
  else if (current_delay > delay_time and accel_mode & 2)
  {
    current_delay = current_delay - step_amount;
  }
  else if (current_delay < delay_time)
  {
    current_delay = current_delay + step_amount;
  }
  delayMicroseconds(current_delay);
  current_step++;
}


void menu_jog_coil(MenuItem* p_menu_item)
{
  byte jog_mode = 0;
  byte jog_dir = 0;
  byte jog_run = 0;
  long jog_speed = conf.coilSpeed;

  lcd.clear();
  lcd.print("Jog coil");

  line = 0;
  print_long(jog_speed);

  lcd.setCursor(10, 0);
  lcd.print("  Man");

  lcd.setCursor(7, 1);
  lcd.print("^");
  lcd.print(" Fwd");
  lcd.setCursor(0, 2);
  lcd.print("Back < ");
  lcd.write(219);
  lcd.print(" Mode  >");
  lcd.setCursor(7, 3);
  lcd.print("v Rev   Stop");

  while (1)
  {
    check_buttons();
    if (d_state && !d_state_ack)
    {
      // left
      d_state_ack = 1;
      lcd.clear();
      break;
    }
    else if (a_state && !a_state_ack)
    {
      // center
      a_state_ack = 1;
      jog_mode++;
      if (jog_mode > 2)
      {
        jog_mode = 0;
      }
      lcd.setCursor(12, 0);
      if (jog_mode == 0)
      {
        lcd.print("Man ");
      }
      else if (jog_mode == 1)
      {
        lcd.print("Cont");
      }
      else if (jog_mode == 2)
      {
        lcd.print("Fixd");
      }
    }
    else if (e_state && !e_state_ack)
    {
      // left
      e_state_ack = 1;
      lcd.setCursor(10, 0);
      lcd.print(" ");
      jog_run = 0;
    }

    if (jog_mode == 0)
    {
      jog_run = 0;

      // Manual
      if (c_state)
      {
        stepper_enable(4);

        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("F");
        jog_dir = 1;

        digitalWrite(stepper_b_direction, conf.coilInvert ^ jog_dir);  // HIGH = forward
        current_step = 0;

        while (c_state)
        {
          check_buttons();
          digitalWrite(stepper_b_step, LOW);
          delayMicroseconds(20);      // Set delay to match motor driver specs
          digitalWrite(stepper_b_step, HIGH);
          delay_step(conf.guideSteps, 2005, 385, 10, 2);
        }
        current_step = 1;
        while (current_delay < 2000)
        {
          digitalWrite(stepper_b_step, LOW);
          delayMicroseconds(20);      // Set delay to match motor driver specs
          digitalWrite(stepper_b_step, HIGH);
          delay_step(82, 2005, 385, 20, 1);
        }
        lcd.setCursor(10, 0);
        lcd.print(" ");
        stepper_enable(5);
      }
      if (b_state)
      {
        stepper_enable(4);

        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("R");
        jog_dir = 0;

        digitalWrite(stepper_b_direction, conf.coilInvert ^ jog_dir);  // HIGH = forward
        current_step = 0;

        while (b_state)
        {
          check_buttons();
          digitalWrite(stepper_b_step, LOW);
          delayMicroseconds(20);
          digitalWrite(stepper_b_step, HIGH);
          delay_step(conf.coilSteps, 2005, 385, 10, 2);
        }
        current_step = 1;
        while (current_delay < 2000)
        {
          digitalWrite(stepper_b_step, LOW);
          delayMicroseconds(20);      // Set delay to match motor driver specs
          digitalWrite(stepper_b_step, HIGH);
          delay_step(82, 2005, 385, 20, 1);
        }
        lcd.setCursor(10, 0);
        lcd.print(" ");
        stepper_enable(5);
      }
    }
    else if (jog_mode == 1)
    {
      // Continuous
      if (!c_state_ack and c_state and (!jog_run or (jog_run and !jog_dir)))
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("F");
        jog_dir = 1;
        jog_run = 1;
        current_step = 0;
        stepper_enable(4);

        digitalWrite(stepper_b_direction, conf.coilInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!c_state_ack and c_state and jog_run)
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (!b_state_ack and b_state and (!jog_run or (jog_run and jog_dir)))
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("R");
        jog_dir = 0;
        jog_run = 1;
        current_step = 0;
        stepper_enable(4);

        digitalWrite(stepper_b_direction, conf.coilInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!b_state_ack and b_state and jog_run)
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (jog_run)
      {
        digitalWrite(stepper_b_step, LOW);
        delayMicroseconds(20);      // Set delay to match motor driver specs
        digitalWrite(stepper_b_step, HIGH);
        delay_step(conf.coilSteps, 2005, 385, 10, 2);
      }
      else
      {
        current_step = 1;
        while (current_delay < 2000)
        {
          digitalWrite(stepper_b_step, LOW);
          delayMicroseconds(20);      // Set delay to match motor driver specs
          digitalWrite(stepper_b_step, HIGH);
          delay_step(82, 2005, 385, 20, 1);
        }
        stepper_enable(5);
      }
    }
    else if (jog_mode == 2)
    {
      // Fixed
      jog_run = 0;

      if (!c_state_ack and c_state and (!jog_run or (jog_run and !jog_dir)))
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("F");
        jog_dir = 1;
        jog_run = 1;
        stepper_enable(4);

        digitalWrite(stepper_b_direction, conf.coilInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!c_state_ack and c_state and jog_run)
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (!b_state_ack and b_state and (!jog_run or (jog_run and jog_dir)))
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("R");
        jog_dir = 0;
        jog_run = 1;
        stepper_enable(4);

        digitalWrite(stepper_b_direction, conf.coilInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!b_state_ack and b_state and jog_run)
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (jog_run)
      {
        current_step = 0;
        for (long i = 0 ; i < conf.coilSteps ; i++)
        {
          check_buttons();
          if (e_state && !e_state_ack)
          {
            // left
            e_state_ack = 1;
            lcd.setCursor(10, 0);
            lcd.print(" ");
            jog_run = 0;
            break;
          }

          digitalWrite(stepper_b_step, LOW);
          delayMicroseconds(20);
          digitalWrite(stepper_b_step, HIGH);
          delay_step(conf.coilSteps, 2000, 385, 5, 3);
        }
        jog_run = 0;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        stepper_enable(5);
      }
    }
  }
}

void menu_jog_guide(MenuItem* p_menu_item)
{
  byte jog_mode = 0;
  byte jog_dir = 0;
  byte jog_run = 0;
  long jog_speed = conf.coilSpeed;

  lcd.clear();
  lcd.print("Jog guide");

  line = 0;
  print_long(jog_speed);

  lcd.setCursor(10, 0);
  lcd.print("  Man");

  lcd.setCursor(7, 1);
  lcd.print("^");
  lcd.print(" Fwd");
  lcd.setCursor(0, 2);
  lcd.print("Back < ");
  lcd.write(219);
  lcd.print(" Mode  >");
  lcd.setCursor(7, 3);
  lcd.print("v Rev   Stop");

  while (1)
  {
    check_buttons();

    if (d_state && !d_state_ack)
    {
      // left
      d_state_ack = 1;
      lcd.clear();
      break;
    }
    else if (a_state && !a_state_ack)
    {
      // center
      a_state_ack = 1;
      jog_mode++;
      if (jog_mode > 2)
      {
        jog_mode = 0;
      }
      lcd.setCursor(12, 0);
      if (jog_mode == 0)
      {
        lcd.print("Man ");
      }
      else if (jog_mode == 1)
      {
        lcd.print("Cont");
      }
      else if (jog_mode == 2)
      {
        lcd.print("Fixd");
      }
    }
    else if (e_state && !e_state_ack)
    {
      // left
      e_state_ack = 1;
      lcd.setCursor(10, 0);
      lcd.print(" ");
      jog_run = 0;
    }

    if (jog_mode == 0)
    {
      jog_run = 0;

      // Manual
      if (c_state && max_state)
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("F");
        jog_dir = 1;
        stepper_enable(4);

        digitalWrite(stepper_a_direction, conf.guideInvert ^ jog_dir);  // HIGH = forward
        current_step = 0;

        while (c_state && max_state)
        {
          check_buttons();
          digitalWrite(stepper_a_step, LOW);
          delayMicroseconds(20);      // Set delay to match motor driver specs
          digitalWrite(stepper_a_step, HIGH);
          delay_step(conf.guideSteps, 2005, 385, 10, 2);
        }
        if (max_state)
        {
          current_step = 1;
          while (current_delay < 2000)
          {
            digitalWrite(stepper_a_step, LOW);
            delayMicroseconds(20);      // Set delay to match motor driver specs
            digitalWrite(stepper_a_step, HIGH);
            delay_step(82, 2005, 385, 20, 1);
          }
          stepper_enable(5);
        }
        else
        {
          jog_run = 0;
          current_delay = 2000;
        }
        lcd.setCursor(10, 0);
        lcd.print(" ");
      }
      if (b_state && min_state)
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("R");
        jog_dir = 0;
        stepper_enable(4);

        digitalWrite(stepper_a_direction, conf.guideInvert ^ jog_dir);  // HIGH = forward
        current_step = 0;

        while (b_state && min_state)
        {
          check_buttons();
          digitalWrite(stepper_a_step, LOW);
          delayMicroseconds(20);
          digitalWrite(stepper_a_step, HIGH);
          delay_step(conf.guideSteps, 2005, 385, 10, 2);
        }
        if (min_state)
        {
          current_step = 1;
          while (current_delay < 2000)
          {
            digitalWrite(stepper_a_step, LOW);
            delayMicroseconds(20);      // Set delay to match motor driver specs
            digitalWrite(stepper_a_step, HIGH);
            delay_step(82, 2005, 385, 20, 1);
          }
          stepper_enable(5);
        }
        else
        {
          jog_run = 0;
          current_delay = 2000;
        }
        lcd.setCursor(10, 0);
        lcd.print(" ");
      }
    }
    else if (jog_mode == 1)
    {
      // Continuous
      if (!c_state_ack and c_state and (!jog_run or (jog_run and !jog_dir)))
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("F");
        jog_dir = 1;
        jog_run = 1;
        current_step = 0;
        stepper_enable(4);

        digitalWrite(stepper_a_direction, conf.guideInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!c_state_ack and c_state and jog_run)
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (!b_state_ack and b_state and (!jog_run or (jog_run and jog_dir)))
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("R");
        jog_dir = 0;
        jog_run = 1;
        current_step = 0;
        stepper_enable(4);

        digitalWrite(stepper_a_direction, conf.guideInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!b_state_ack and b_state and jog_run)
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (jog_run && min_state && max_state)
      {
        digitalWrite(stepper_a_step, LOW);
        delayMicroseconds(20);      // Set delay to match motor driver specs
        digitalWrite(stepper_a_step, HIGH);
        delay_step(conf.guideSteps, 2005, 385, 10, 2);
      }
      else if (!min_state || !max_state)
      {
        // stop immediately
        jog_run = 0;
        current_delay = 2000;
      }
      else
      {
        current_step = 1;
        while (current_delay < 2000)
        {
          digitalWrite(stepper_a_step, LOW);
          delayMicroseconds(20);      // Set delay to match motor driver specs
          digitalWrite(stepper_a_step, HIGH);
          delay_step(82, 2005, 385, 20, 1);
        }
        stepper_enable(5);

      }
    }
    else if (jog_mode == 2)
    {
      // Fixed
      jog_run = 0;

      if (!c_state_ack and c_state and (!jog_run or (jog_run and !jog_dir)))
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("F");
        jog_dir = 1;
        jog_run = 1;
        stepper_enable(4);

        digitalWrite(stepper_a_direction, conf.guideInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!c_state_ack and c_state and jog_run)
      {
        c_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (!b_state_ack and b_state and (!jog_run or (jog_run and jog_dir)))
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print("R");
        jog_dir = 0;
        jog_run = 1;
        stepper_enable(4);

        digitalWrite(stepper_a_direction, conf.guideInvert ^ jog_dir);  // HIGH = forward
      }
      else if (!b_state_ack and b_state and jog_run)
      {
        b_state_ack = 1;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        jog_run = 0;
      }

      if (jog_run && ((!jog_dir && min_state) || (jog_dir && max_state)))
      {
        current_step = 0;
        for (long i = 0 ; i < conf.guideSteps ; i++)
        {
          check_buttons();
          if ((e_state && !e_state_ack) || (!jog_dir && !min_state) || (jog_dir && !max_state))
          {
            // left
            e_state_ack = 1;
            lcd.setCursor(10, 0);
            lcd.print(" ");
            jog_run = 0;
            break;
          }

          digitalWrite(stepper_a_step, LOW);
          delayMicroseconds(20);
          digitalWrite(stepper_a_step, HIGH);
          delay_step(conf.guideSteps, 1000, 385, 5, 3);
        }
        jog_run = 0;
        current_delay = 2000;
        lcd.setCursor(10, 0);
        lcd.print(" ");
        stepper_enable(5);
      }
    }
  }
}

void menu_settings_coilsteps(MenuItem* p_menu_item)
{
  conf.coilSteps = edit_long(conf.coilSteps);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_settings_coilinvert(MenuItem* p_menu_item)
{
  conf.coilInvert = conf.coilInvert ^ 1;
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_settings_guidesteps(MenuItem* p_menu_item)
{
  conf.guideSteps = edit_long(conf.guideSteps);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_settings_guideinvert(MenuItem* p_menu_item)
{
  conf.guideInvert = conf.guideInvert ^ 1;
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_home_guide(MenuItem* p_menu_item)
{
  // home guide
  lcd.setCursor(0, 3);
  lcd.print("Homing Guide        ");

  current_step = 0;
  stepper_enable(4);

  digitalWrite(stepper_a_direction, conf.guideInvert ^ 0);  // HIGH = forward

  while (min_state)
  {
    check_buttons();
    if ((e_state && !e_state_ack) || (!min_state) || (!max_state))
    {
      // left
      e_state_ack = 1;
      break;
    }

    digitalWrite(stepper_a_step, LOW);
    delayMicroseconds(20);      // Set delay to match motor driver specs
    digitalWrite(stepper_a_step, HIGH);
    delay_step(conf.guideSteps, 2005, 385, 10, 2);
  }
  current_delay = 2000;

  digitalWrite(stepper_a_direction, conf.guideInvert ^ 1);  // HIGH = forward

  unsigned long total_steps = conf.coilHome * conf.guideSteps / 1000;


  current_step = 0;
  for (unsigned long i = 0 ; i < total_steps ; i++)
  {
    check_buttons();
    if ((e_state && !e_state_ack) || !max_state)
    {
      // left
      e_state_ack = 1;
      break;
    }
    digitalWrite(stepper_a_step, LOW);
    delayMicroseconds(20);
    digitalWrite(stepper_a_step, HIGH);
    delay_step(total_steps, 1000, 385, 5, 3);
  }

  current_delay = 2000;
  stepper_enable(5);

  lcd.setCursor(0, 3);
  lcd.print("              ");
}

void menu_job_wiredia(MenuItem* p_menu_item)
{
  conf.wireSize = edit_long(conf.wireSize);
  calc_coil(0);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_job_help(MenuItem* p_menu_item)
{

}

void menu_job_coildia(MenuItem* p_menu_item)
{
  conf.coilDiam = edit_long(conf.coilDiam);
  calc_coil(0);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_job_coilhome(MenuItem* p_menu_item)
{
  conf.coilHome = edit_long(conf.coilHome);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_job_length(MenuItem* p_menu_item)
{
  conf.coilLength = edit_long(conf.coilLength);
  calc_coil(1);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_job_turns(MenuItem* p_menu_item)
{
  conf.coilTurns = edit_long(conf.coilTurns);
  calc_coil(2);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_job_speed(MenuItem* p_menu_item)
{
  conf.coilSpeed = edit_long(conf.coilSpeed);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_job_calc(MenuItem* p_menu_item)
{
  conf.coilCalc = conf.coilCalc ^ 1;
  calc_coil(0);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void menu_job_ratio(MenuItem* p_menu_item)
{
  conf.coilRatio = edit_float(conf.coilRatio);
  calc_coil(0);
  eeprom_write_block((const void*)&conf, (void*)0, sizeof(conf));
}

void calc_coil(byte calc_type)
{
  // calculate the coil size based on secondary diameter, ratio, and wire size
  if (conf.coilCalc)
  {
    if (calc_type == 0)
    {
      // using wire diam, coil diam, and ratio
      conf.coilLength = conf.coilDiam * conf.coilRatio;
      conf.coilTurns = conf.coilLength / conf.wireSize;
    }
    else if (calc_type == 1)
    {
      // using wire diam, coil diam, and lenght
      float i = (float) (conf.coilLength / conf.coilDiam) * 100 + 0.5;
      conf.coilRatio = i / 100;
      conf.coilTurns = conf.coilLength / conf.wireSize;
    }
    else if (calc_type == 2)
    {
      // using wire diam, coil diam, and turns
      conf.coilLength = conf.coilTurns * conf.wireSize;
      float i = (float) (conf.coilLength / conf.coilDiam) * 100 + 0.5;

      conf.coilRatio = i / 100;
    }
  }
}

void menu_job_start(MenuItem* p_menu_item)
{

  // Coil Winding Subroutine

  int max_speed = 200;   // Fast
  int min_speed = 800;  // Slow
  int set_speed = 800;   // Current Speed
  int saved_set_speed = set_speed;

  byte pause = 0;
  long guide_steps = 0;
  char buf[16];
  ltoa(conf.coilTurns, buf, 10);  // 10 is the base value not the size - look up ltoa for avr
  int len_buf = strlen(buf);

  char buf2[16];

  lcd.clear();
  lcd.print("Winding");
  lcd.setCursor(0, 1);
  lcd.print("Total Turns:");
  lcd.setCursor(0, 2);
  lcd.print("[] Pause  > Stop");

  byte end_job = 0;
  current_step = 0;

  ltoa(0, buf2, 10);  // 10 is the base value not the size - look up ltoa for avr
  lcd.setCursor(13, 1);
  //  lcd.print(buf2);
  //  lcd.setCursor(11 + len_buf, 1);
  //  lcd.print("/");
  lcd.print(buf);

  if (!stepper_a_ena)
  {
    stepper_enable(1);
  }

  digitalWrite(stepper_a_direction, conf.guideInvert ^ 1);  // HIGH = forward
  digitalWrite(stepper_b_direction, conf.coilInvert ^ 1);  // HIGH = forward


  // calculate our loop value
  unsigned long coil_steps = (conf.wireSize * conf.guideSteps) / 1000; // use guide steps for coil
  unsigned long total_coil_steps = conf.coilSteps * conf.coilTurns; // use guide steps for coil
  unsigned long loop_steps = conf.coilSteps * guide_steps;

  unsigned long loop_counter = 0;
  unsigned long guide_counter = 0;
  unsigned long coil_counter = 0;
  unsigned long foo_counter = 0;
  unsigned long winding_counter = 0;
  unsigned long intersections = 0;

  for (long x = 0 ; x < total_coil_steps ; x = x + conf.coilSteps)
  {
    if (x % coil_steps)
    {
      intersections++;
    }
  }

  total_coil_steps = total_coil_steps + (conf.coilTurns * conf.wireSize / 1000 * conf.guideSteps) - intersections - conf.coilSteps;

  while (winding_counter < conf.coilTurns)
  {

    loop_counter++;
    guide_counter++;
    coil_counter++;
    int delaynow = 0;
    if (guide_counter >= conf.coilSteps)
    {
      digitalWrite(stepper_a_step, LOW);
      delaynow = 1;
    }

    if (coil_counter >= coil_steps)
    {
      digitalWrite(stepper_b_step, LOW);
      delaynow = 1;
    }

    if (delaynow)
    {
      delayMicroseconds(max_speed);
    }

    if (guide_counter >= conf.coilSteps)
    {
      guide_counter = 0;
      digitalWrite(stepper_a_step, HIGH);
    }

    if (coil_counter >= coil_steps)
    {

      // check input
      check_buttons();
      if (e_state && !e_state_ack)
      {
        // left - stop
        e_state_ack = 1;
        break;
      }

      if (a_state && !a_state_ack)
      {
        // left - pause
        a_state_ack = 1;

        // Timing is very crucial when you are running stepper and want a smooth speed,
        // so much of the informational LCD information is disabled while winding to prevent
        // undesired micro-stops

        //        lcd.setCursor(0,3);
        if (!pause)
        {
          //          lcd.print("Paused");
          pause = 1;
          saved_set_speed = set_speed;
          set_speed = min_speed;
        }
        else
        {
          //          lcd.print("      ");
          pause = 0;
          set_speed = saved_set_speed;
        }
      }

      if (pause && current_delay == set_speed)
      {
        while (1)
        {
          check_buttons();
          if (a_state && !a_state_ack)
          {
            // left - pause
            a_state_ack = 1;
            pause = 0;
            set_speed = saved_set_speed;
            break;
          }
          if (e_state && !e_state_ack)
          {
            break;
          }
        }
        if (e_state && !e_state_ack)
        {
          // left - stop
          e_state_ack = 1;
          break;
        }
      }

      if (b_state && !b_state_ack)
      {
        // down
        b_state_ack = 1;
        set_speed = set_speed * 2;
        if (set_speed > min_speed)
        {
          set_speed = min_speed;
        }
        lcd.setCursor(10, 0);
        lcd.print(set_speed);
      }

      if (c_state && !c_state_ack)
      {
        // up
        c_state_ack = 1;
        set_speed = set_speed / 2;
        if (set_speed < max_speed)
        {
          set_speed = max_speed;
        }
        lcd.setCursor(10, 0);
        lcd.print(set_speed);
      }

      coil_counter = 0;
      foo_counter++;
      if (foo_counter >= conf.coilSteps)
      {
        foo_counter = 0;
        winding_counter++;
      }
      digitalWrite(stepper_b_step, HIGH);
    }

    if (delaynow)
    {
      delay_step(total_coil_steps, min_speed, set_speed, 5, 3);
    }
  }

  lcd.clear();
  lcd.print("Winding");
  lcd.setCursor(0, 1);
  lcd.print("     Complete");
  lcd.setCursor(0, 2);
  lcd.print("< Return");

  while (1)
  {
    check_buttons();
    if (d_state && !d_state_ack)
    {
      // left - stop
      d_state_ack = 1;
      break;
    }
  }

  stepper_enable(0);
}

void print_status(long turn_number)
{
  /*
     this function largely abandoned due to it taking too
    much time.  I'm sure the code could be rewritten to be
    a bit more efficient about things, but we're not there
    just yet.

      12345678901234567890
     [Winding         65% ]
     [     Turn:   345/814]
     [ Position:    234234]
     [   Meters:     12345]
  */
  char buf[16];
  char buf2[16];
}
 

Attachments

  • tesla_winder_teensy20.ino
    44.7 KB · Views: 249
Last edited:
Oh hell, please edit your post and put code tags around your code. (Select the code from beginning to the end with the mouse and then click the # in the editor toolbar.
 
Status
Not open for further replies.
Back
Top