Diy Spot welder using Arduino nano

/***************************** Code for Arduino Spot Welder *****************************/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>

// CONNECT SDA PIN AND SCL PIN OF LCD AND DS3231 TO A4 AND A5 OF ADRUINO RESPECTIVELY.
LiquidCrystal_I2C lcd(0x27, 20, 4);
DS3231 rtc(SDA, SCL);

// ROTORY ENCODER RELATED PINS
const int clkPin = 8;  // A
const int dataPin = 9; // B
const int swPin = 10;  // Button of rotory encoder
int getEncoderMovement();

// FOOT SWITCH RELATED PINS
const int weldBtn = 13; 

// RELAY TRIGGER RELATED PINS
const int weldOutput = 12; // relay input

long buttonStartTime = 0;
long buttonEndTime = 0;
long charTimeStart = 0;
long charTimeEnd = 0;
int menuSwitchTime = 2; // Seconds of constant button push to SWITCH Modes
int menuChoice = 1;
int oldMenuChoice = 1;
int pulseChoice = 1;

bool optionsMode = false;
bool weldBtnDown = false;
bool characterVisible = false;
bool enterMode = false;
bool modeChanged = false;
bool oneTwoPulse = false;

//********** RTC Related Variables ***********//
String currentClock, currentHours, currentMinutes, currentSeconds, currentDate, currentDay, currentMonth, currentYear;
String timeString, hoursString, minutesString, secondsString, hoursS, minutesS, secondsS, dateS;
float currentTemparature, temparature;
//********************************************//

//********** PULSE Related initial settings*******************//
long pulseLength = 100;       // One Milli-Second (1ms) is minimum duration
int pulses = 2;               // Zero to Five (Zero = one-two pulse)
int firstPulse = 100;         // first pulse only for one-two pulse option
int secondPulse = 100;        // second pulse only for one-two pulse option
int delayBetweenPulses = 50;  // 50 milli-Second is minimum and 500 milli-Second is maximum
//********************************************//

void intro();
void initialiseClock();
void menu();
void updateTime();
void createCharacter();
void showCorrectDisplay(int menuChoice, bool displacement);
void showSetChoice();
void correctDisplay();

byte fullSquare[8] = 
{
  B01000,
  B00100,
  B00010,
  B11111,
  B11111,
  B00010,
  B00100,
  B01000
};


/***********************************************************************************************************
 * FUNCTION NAME :- setup
 * USAGE         :- This Function execute once at stating of the program and set all required fields
 *                  as user wants.
 ***********************************************************************************************************/
void setup() {
  pinMode(clkPin, INPUT);
  pinMode(dataPin, INPUT);
  pinMode(swPin, INPUT);
  pinMode(weldBtn, INPUT);
  pinMode(weldOutput, OUTPUT);
  digitalWrite(swPin, HIGH);
  
  {
    lcd.init();    // initializing the LCD
    lcd.backlight();
  }

  intro();
  menu();
}


/***********************************************************************************************************
 * FUNCTION NAME :- loop
 * USAGE         :- This Function execute repeatedly for infinite number of times(heart of the program).
 ***********************************************************************************************************/
void loop() {
  start:
  createCharacter();

  // WELD MODE
  if (!optionsMode)
  {
    if (digitalRead(swPin) == LOW)
    {
      while (modeChanged)
      {
        // TO PREVENT THE MODES FROM CONSTANTLY CHANGING, THE USER MUST LEAVE THE BUTTON IF THEY WANTS TO CHANGE THE MODES AGAIN
        if (digitalRead(swPin) == HIGH)
        {
          modeChanged = false;
          goto start;
        }
        updateTime();
      }
      buttonStartTime = rtc.getUnixTime(rtc.getTime());
      lcd.setCursor(19, 0);
      lcd.print("!");
      while (digitalRead(swPin) == LOW)
      {
        // GOING TO OPTIONS MODE
        buttonEndTime = rtc.getUnixTime(rtc.getTime());
        updateTime();
        if ((buttonEndTime - buttonStartTime) >= menuSwitchTime)
        {
          optionsMode = true;
          modeChanged = true;
          menu();
          showCorrectDisplay(menuChoice, false);
          goto start;
        }
      }
      lcd.setCursor(19, 0);
      lcd.print(" "); 
    }

    // TO DO :- CLOCK DOESN'T WORK WHEN WELDING IS IN PROCESS !! (CHANGE IT BY USING TIMERS)
    if (digitalRead(weldBtn) == HIGH)
    {
      // WELD - BUTTON --> comment if button is not considered
      delay(100);
      while (digitalRead(weldBtn) == HIGH)
      {
        if (!weldBtnDown)
        {
          if (oneTwoPulse)
          {
            digitalWrite(weldOutput, HIGH);
            delay(firstPulse);
            digitalWrite(weldOutput, LOW);
            delay(delayBetweenPulses);
            digitalWrite(weldOutput, HIGH);
            delay(secondPulse);
            digitalWrite(weldOutput, LOW);
            updateTime();
          }
      
          else if (pulses > 1)
          {
            for (int i = 1; i <= pulses; i++)
            {
              digitalWrite(weldOutput, HIGH);
              delay(pulseLength);
              digitalWrite(weldOutput, LOW);
              delay(delayBetweenPulses);
              updateTime();
            }
          }

          else
          {
            digitalWrite(weldOutput, HIGH);
            delay(pulseLength);
            digitalWrite(weldOutput, LOW);
            updateTime();
          }
          weldBtnDown = true; 
        }
        updateTime();
      }
    }
    weldBtnDown = false;

    updateTime();    
  }
  else
  {
    // OPTIONS - MODE
    int encMove = 0;
    encMove = getEncoderMovement();
    menuChoice += encMove;
    if (menuChoice > 4)
    {
      // CHECK IF MENUCHOICE IS OUT OF THE BOUNDS AFTER THE MOVEMENT
      menuChoice = 1;
    }
    else if (menuChoice < 1)
    {
      menuChoice = 4;
    }

    // delayBetweenPulses IS NOT USED ON ONE PULSE. SO, WE SKIP THAT SETTING WHEN WE ONLY HAVE A SINGLE PULSE.
    if ((pulses == 1) && (menuChoice == 3) && (oldMenuChoice == 2))
    {
      menuChoice = 4;
    }
    else if ((pulses == 1) && (menuChoice == 3) && (oldMenuChoice == 4))
    {
      menuChoice = 2;
    }

    if (menuChoice != oldMenuChoice)
    {
      menu();       // PUT EVERY LINE BACK IN PLACE
      oldMenuChoice = menuChoice;
    }

    showCorrectDisplay(menuChoice, false);
    updateTime();

    if (digitalRead(swPin) == LOW)
    {
      // GOING TO WELD-MODE OR OPTIONS MODE
      while (modeChanged)
      {
        // TO PREVENT THE MODES FROM CONSTANTLY CHANGING. THE USER MUST LEAVE THE BUTTON IF THEY WANTS TO CHANGE MODE AGAIN
        if (digitalRead(swPin) == HIGH)
        {
          modeChanged = false;
          goto start;
        }
        updateTime();
      }

      buttonStartTime = rtc.getUnixTime(rtc.getTime());
      lcd.setCursor(19, 0);
      lcd.print("!");
      while (digitalRead(swPin) == LOW)
      {
        buttonEndTime = rtc.getUnixTime(rtc.getTime());
        updateTime();
        if ((buttonEndTime - buttonStartTime) >= menuSwitchTime)
        {
          optionsMode = false;
          modeChanged = true;
          menu();
          goto start;
        }
      }
      lcd.setCursor(19, 0);     // Deletes "!" when entering Enter Mode
      lcd.print(" ");

      enterMode = true;     // IF THE USER PRESS THE ENCODER BUTTON AND LEAVES IT BEFORE THE 'X' SEC. MARK, THE USER WILL BE ENTERED IN enterMode AND NOW CAN CHANGE THE VALUES.
      modeChanged = true;
      if (enterMode)
      {
        int encPosition = 0;
        int encOldPosition = 0;
        menu();
        showSetChoice();

        lcd.setCursor(3, menuChoice - 1);   // THE USER WILL SEE A LONG LETTER UNTIL THE correctDisplay is shown, this fixes that.
        lcd.print(" ");

        while (enterMode)
        {
          updateTime();

          // ONE-TWO PULSE WILL BE SET DIFFERENTLY, BECAUSE THE INPUT METHOD IS DIFFERENT THAN OTHER SETTINGS.
      /* Changes Begin for OneTwoPulse mode only */
          if ((menuChoice == 1) && (oneTwoPulse))
          {
            lcd.setCursor(3, 0);        // FOR THE SAME REASON THE FIRST ":" DISAPPEARS
            lcd.print(":");

            while (true)
            {
              showSetChoice();
              showCorrectDisplay(menuChoice, false);

              encMove = getEncoderMovement();
              encPosition += encMove;

              if (digitalRead(swPin) == LOW)
              {
                delay(125);
                if (digitalRead(swPin) == LOW)
                {
                  pulseChoice++;
                }

                // ERASING THE ARROW WHEN USER CHANGES THE SECOND PULSE
                if (pulseChoice == 2)
                {
                  lcd.setCursor(0, 0);
                  lcd.print(" ");
                }
                else if (pulseChoice == 3)
                {
                  pulseChoice = 1;
                  enterMode = false;
                  modeChanged = true;
                  menu();
                  goto start;
                }
              }

      // WHEN ROTORY ENCODER KNOB IN INCREASING ORDER 
              if (encPosition > encOldPosition)
              {
                switch (pulseChoice)
                {
                  case 1: 
                        {
                          if (firstPulse == 9995)
                          {
                            // 9995 Milli - Second IS THE MAXIMUM
                            firstPulse = 1; 
                          }
                          else
                          {
                            if (firstPulse < 10)
                            {
                              firstPulse++;
                            }
                            else
                            {
                              firstPulse += 5;
                            }
                          }
                          correctDisplay();
                          break;
                        }

                  case 2:
                        {
                          if (secondPulse == 9995)
                          {
                            // 9995 Milli - Second IS THE MAXIMUM
                            secondPulse = 1; 
                          }
                          else
                          {
                            if (secondPulse < 10)
                            {
                              secondPulse++;
                            }
                            else
                            {
                              secondPulse += 5;
                            }
                          }
                          correctDisplay();
                          break;                   
                        }
                }
              }
        
        // WHEN ROTORY ENCODER KNOB IN DECREASING ORDER
              else if (encPosition < encOldPosition)
              {
                switch (pulseChoice)
                {
                  case 1:
                        {
                          if (firstPulse == 1)
                          {
                          // 9995 Milli - Second IS THE MAXIMUM
                          firstPulse = 9995;
                          }
                          else
                          {
                            if (firstPulse <= 10)
                            {
                              firstPulse--;
                            }
                            else
                            {
                              firstPulse -= 5;
                            }
                          }
                          correctDisplay();
                          break;
                        }
                        
                  case 2:
                        {
                          if (secondPulse == 1)
                          {
                            // 9995 Milli - Second IS THE MAXIMUM
                            secondPulse = 9995;
                          }
                          else
                          {
                            if (secondPulse <= 10)
                            {
                              secondPulse--;
                            }
                            else
                            {
                              secondPulse -= 5;
                            }
                          }
                          correctDisplay();
                          break;
                        }                          
                  }
                }
                encOldPosition = encPosition;
                updateTime();
              } 
            }
/* changes end for OneTwoPulse */

            showCorrectDisplay(menuChoice, true);

            encMove = getEncoderMovement();
            encPosition += encMove;
      
      // WHEN ROTORY ENCODER KNOB IN INCREASING ORDER
            if (encPosition > encOldPosition)
            {
              switch (menuChoice)
              {
                case 1:
                      {
                        if (pulseLength == 999995)
                        {
                          // 999995 Milli-Second IS THE MAXIMUM LIMIT FOR PULSE LENGTH (WONT BE USED ANY WAY)
                          pulseLength = 1;
                          lcd.setCursor(3, menuChoice - 1);
                          lcd.print(" ");
                          showSetChoice();
                          correctDisplay();
                        }
                        else
                        {
                          if (pulseLength < 10)
                          {
                            pulseLength += 1;
                          }
                          else
                          {
                            pulseLength += 5;
                          }
                          showSetChoice();
                          correctDisplay();
                        }
                        break;
                      }


                case 2:
                      {
                        if (pulses == 5)
                        {
                          pulses = 0;
                          oneTwoPulse = true;
                          lcd.setCursor(3, menuChoice - 1);
                          lcd.print(" ");
                          showSetChoice();
                        }
                        else
                        {
                          pulses++;
                          if (pulses > 0)
                          {
                            oneTwoPulse = false;
                          }
                          showSetChoice();
                        }
                        break;
                      }

                 
                case 3:
                      {
                        if (delayBetweenPulses == 500)
                        {
                          delayBetweenPulses = 50;    // MAXIMUM LIMIT FOR DELAY BETWEEN PULSES 
                          lcd.setCursor(3, menuChoice - 1);
                          lcd.print(" ");
                          showSetChoice();
                        }
                        else
                        {
                          delayBetweenPulses += 50;
                          showSetChoice();
                        }
                        correctDisplay();
                        break;
                      }


                case 4:
                      {
                        // TO DO :- TIME SET
            break;
                      }
              }  
          }

      // WHEN ROTORY ENCODER KNOB IN DECREASING ORDER
          else if (encPosition < encOldPosition)
          {
            switch (menuChoice)
            {
              case 1:
                    {
                      if (pulseLength == 1)
                      {
                        pulseLength = 999995;
                        lcd.setCursor(3, menuChoice - 1);
                        lcd.print(" ");
                        showSetChoice();
                        correctDisplay();
                      }
                      else
                      {
                        if (pulseLength <= 10)
                        {
                          pulseLength -= 1;
                        }
                        else
                        {
                          pulseLength -= 5;
                        }
                        showSetChoice();
                        correctDisplay();
                      }
                      break;
                    }


              case 2:
                    {
                      if (pulses == 0)
                      {
                        pulses = 5;
                        oneTwoPulse = false;
                        lcd.setCursor(3, menuChoice - 1);
                        lcd.print(" ");
                        showSetChoice();                       
                      }
                      else
                      {
                        pulses--;
                        if (pulses == 0)
                        {
                          oneTwoPulse = true;
                        }
                        showSetChoice();  
                      }
                      break;
                    }

                    
              case 3:
                    {
                      if (delayBetweenPulses == 50)
                      {
                        delayBetweenPulses = 500;
                        lcd.setCursor(3, menuChoice - 1);
                        lcd.print(" ");
                        showSetChoice();
                      }
                      else
                      {
                        delayBetweenPulses -= 50;
                        showSetChoice();
                      }
                      correctDisplay();
                      break;
                    }

              case 4:
                    {
                      //TO DO :- Set Time / Date
                      break;
                    }      
            }
          }

    // WHEN NO MOVEMENT IN ROTORY ENCODER
          encOldPosition = encPosition;

          if (digitalRead(swPin) == LOW)
          {
            // EXITING ENTER MODE
            delay(100);
            if (digitalRead(swPin) == LOW)
            {
              enterMode = false;
              modeChanged = true;
              menu();
              goto start;
            }
          }
        }
      }
    }  
  }
}

/***********************************************************************************************************
 * FUNCTION NAME :- intro
 * USAGE         :- This Function introduce about product and creator.
 * Note          :- Make changes on below "add_here" and replace with what to be displayed on screen as 
 *                  introduction.
 ***********************************************************************************************************/
void intro()
{
  lcd.setCursor(2, 1);
  lcd.print("add_here"); // MODIFY "add_here" and enter the name which want to be display in starting on second line, e.g., Anukesh Ambatkar.
  lcd.setCursor(9, 2);
  lcd.print("add_here"); // MODIFY "add_here" and enter the name which want to be display in starting on third line, e.g., spot welder.
  delay(3500);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Setting Clock");
  delay(250);     // If want to load the machine faster, these delay's can be reduce.
  lcd.print(".");
  delay(250);
  lcd.print(".");
  delay(250);
  lcd.print(".");

  initializeClock();

  lcd.setCursor(0, 1);
  lcd.print("Done!");
  delay(1000);

  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("(c) 2023");
  lcd.setCursor(5, 1);
  lcd.print("add_here");     // MODIFY "add_here" and enter the name which want to be display in starting on second line, e.g., Anukesh Ambatkar.
  lcd.setCursor(9, 2);
  lcd.print("&");
  lcd.setCursor(5, 3);
  lcd.print("add_here");   // MODIFY "add_here" and enter the name which want to be display in starting on third line, e.g., spot welder.
  delay(2000);
}


/***********************************************************************************************************
 * FUNCTION NAME :- initializeClock
 * USAGE         :- This Function initialize the clock and get current values.
 ***********************************************************************************************************/
void initializeClock()
{
  rtc.begin();

  currentTemparature = rtc.getTemp();
  currentDate = rtc.getDateStr();
  currentClock = rtc.getTimeStr();
  timeString = rtc.getTimeStr();
  currentHours = timeString.substring(0, 2);
  currentMinutes = timeString.substring(3, 5);
  currentSeconds = timeString.substring(6, 8);
}


/***********************************************************************************************************
 * FUNCTION NAME :- menu
 * USAGE         :- This Function holds the different Menu Options and set based on the condition.
 ***********************************************************************************************************/
void menu()
{
  lcd.clear();

  if (pulses == 0)
  {
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("P1: ");
    lcd.print(firstPulse);
    lcd.setCursor(10, 0);
    lcd.print("P2: ");
    lcd.print(secondPulse);
    lcd.setCursor(1, 1);
    lcd.print("One-Two Pulse");
    lcd.setCursor(1, 2);
    lcd.print("Delay: ");
    lcd.print(delayBetweenPulses);
    lcd.print("ms");    
  }
  else
  {
    lcd.setCursor(1, 0);
    lcd.print("Pulse: ");
    lcd.print(pulseLength);
    lcd.print("ms");
    lcd.setCursor(1, 1);
    lcd.print(pulses);
    if (pulses > 1)
    {
      lcd.print(" Pulses");
      lcd.setCursor(1, 2);
      lcd.print("Delay: ");
      lcd.print(delayBetweenPulses);
      lcd.print("ms");
    }
    else
    {
      lcd.print(" Pulse");
      lcd.setCursor(1, 2);
      lcd.print("               ");     // CLEAR LINE
    }
  }

   lcd.setCursor(1, 3);
   lcd.print(rtc.getDateStr());
   lcd.print(" ");
   lcd.print(currentHours);
   lcd.print(":");
   lcd.print(currentMinutes);
   lcd.print(":");
   lcd.print(currentSeconds);   
}


/***********************************************************************************************************
 * FUNCTION NAME :- updateTime
 * USAGE         :- This Function updates the Clock given based on RTC DS3231 and Displays on the 20x4 LCD.
 ***********************************************************************************************************/
void updateTime()
{
  if (currentClock != rtc.getTimeStr())
  {
    timeString = rtc.getTimeStr();
    hoursS = timeString.substring(0, 2);
    minutesS = timeString.substring(3, 5);
    secondsS = timeString.substring(6, 8);

    lcd.setCursor(18, 3);
    lcd.print(secondsS);

    if (currentMinutes != minutesS)
    {
      lcd.setCursor(15, 3);
      lcd.print(minutesS);
      currentMinutes = minutesS;
    }

    if (currentHours != hoursS)
    {
      lcd.setCursor(12, 3);
      lcd.print(hoursS);
      currentHours = hoursS;
    }

    dateS = rtc.getDateStr();
    delay(10);

    if (currentDate != dateS)
    {
      currentDate = dateS;
      lcd.setCursor(1, 3);
      lcd.print(dateS);
    }
  }
}


/***********************************************************************************************************
 * FUNCTION NAME :- createCharacter
 * USAGE         :- This Function creates character.
 ***********************************************************************************************************/
void createCharacter()
{
  lcd.createChar(0, fullSquare);
}


/***********************************************************************************************************
 * FUNCTION NAME :- showCorrectDisplay
 * USAGE         :- This Function shows the correct display based on the menuChoice and input displacement.
 ***********************************************************************************************************/
void showCorrectDisplay(int menuChoice, bool displacement)
{
  switch (menuChoice)
  {
    case 1:
          {
            // ONLY THE CORRECT DISPLAY WILL MOVE
            if (enterMode)
            {
              // ONLY SHOW THE ARROW ON THESE PLACES IF enterMode IS ON. OTHERWISE ARROW WONT SHOW AT ALL.
              if (oneTwoPulse)
              {
                switch (pulseChoice)
                {
                  case 1:
                        {
                          if (!characterVisible)
                          {
                            charTimeEnd = rtc.getUnixTime(rtc.getTime());
                            if ((charTimeEnd - charTimeStart) >= 1)
                            {
                              charTimeStart = rtc.getUnixTime(rtc.getTime());
                              lcd.setCursor(0, 0);
                              lcd.write(byte(0));
                              characterVisible = true;                              
                            }
                          }
                          else
                          {
                            charTimeEnd = rtc.getUnixTime(rtc.getTime());
                            if ((charTimeEnd - charTimeStart) >= 1)
                            {
                              charTimeStart = rtc.getUnixTime(rtc.getTime());
                              lcd.setCursor(0, 0);
                              lcd.print(" ");
                              characterVisible = false;
                            }
                          }
                          break;
                        }

                  case 2:
                        {
                          if (!characterVisible)
                          {
                            charTimeEnd = rtc.getUnixTime(rtc.getTime());
                            if ((charTimeEnd - charTimeStart) >= 1)
                            {
                              charTimeStart = rtc.getUnixTime(rtc.getTime());
                              lcd.setCursor(9, 0);
                              lcd.write(byte(0));
                              characterVisible = true;
                            }
                          }
                          else
                          {
                            charTimeEnd = rtc.getUnixTime(rtc.getTime());
                            if ((charTimeEnd - charTimeStart) >= 1)
                            {
                              charTimeStart = rtc.getUnixTime(rtc.getTime());
                              lcd.setCursor(9, 0);
                              lcd.print(" ");
                              characterVisible = false;
                            }
                          }
                          break;
                        }
                }
              }
            }
            else
            {
              if (!characterVisible)
              {
                charTimeEnd = rtc.getUnixTime(rtc.getTime());
                if ((charTimeEnd - charTimeStart) >= 1)
                {
                  charTimeStart = rtc.getUnixTime(rtc.getTime());
                  if (displacement)
                  {
                    lcd.setCursor(3, 0);
                  }
                  else
                  {
                    lcd.setCursor(0, 0);
                  }
                  lcd.write(byte(0));
                  characterVisible = true;
                }
              }
              else
              {
                charTimeEnd = rtc.getUnixTime(rtc.getTime());
                if ((charTimeEnd - charTimeStart) >= 1)
                {
                  charTimeStart = rtc.getUnixTime(rtc.getTime());
                  if (displacement)
                  {
                    lcd.setCursor(3, 0);
                  }
                  else
                  {
                    lcd.setCursor(0, 0);
                  }
                  lcd.print(" ");
                  characterVisible = false;
                }
              }
            }
            break;
          }
    case 2:
          {
            lcd.setCursor(0, 1);
            if (!characterVisible)
            {
              charTimeEnd = rtc.getUnixTime(rtc.getTime());
              if ((charTimeEnd - charTimeStart) >= 1)
              {
                charTimeStart = rtc.getUnixTime(rtc.getTime());
                if (displacement)
                {
                  lcd.setCursor(3, 1);
                }
                else
                {
                  lcd.setCursor(0, 1);
                }
                lcd.write(byte(0));
                characterVisible = true;
              }
            }
            else
              {
                charTimeEnd = rtc.getUnixTime(rtc.getTime());
                if ((charTimeEnd - charTimeStart) >= 1)
                {
                  charTimeStart = rtc.getUnixTime(rtc.getTime());
                  if (displacement)
                  {
                    lcd.setCursor(3, 1);
                  }
                  else
                  {
                    lcd.setCursor(0, 1);
                  }
                  lcd.print(" ");
                  characterVisible = false;
                }
              }
              break;
          }
          
    case 3:
          {
            lcd.setCursor(0, 2);
            if (!characterVisible)
            {
              charTimeEnd = rtc.getUnixTime(rtc.getTime());
              if ((charTimeEnd - charTimeStart) >= 1)
              {
                charTimeStart = rtc.getUnixTime(rtc.getTime());
                if (displacement)
                {
                  lcd.setCursor(3, 2);
                }
                else
                {
                  lcd.setCursor(0, 2);
                }
                lcd.write(byte(0));
                characterVisible = true;
              }
            }
            else
            {
              charTimeEnd = rtc.getUnixTime(rtc.getTime());
              if ((charTimeEnd - charTimeStart) >= 1)
              {
                charTimeStart = rtc.getUnixTime(rtc.getTime());
                if (displacement)
                {
                  lcd.setCursor(3, 2);
                }
                else
                {
                  lcd.write(byte(0));
                  characterVisible = true;
                }
              }
              else
              {
                charTimeEnd = rtc.getUnixTime(rtc.getTime());
                if ((charTimeEnd - charTimeStart) >= 1)
                {
                  charTimeStart = rtc.getUnixTime(rtc.getTime());
                  if (displacement)
                  {
                    lcd.setCursor(3, 2);
                  }
                  else
                  {
                    lcd.setCursor(0, 2);
                  }
                  lcd.print(" ");
                  characterVisible = false;
                }              
              } 
            }
            break;
          }

          
    case 4:
          {
            lcd.setCursor(0, 3);
            if (!characterVisible)
            {
              charTimeEnd = rtc.getUnixTime(rtc.getTime());
              if ((charTimeEnd - charTimeStart) >= 1)
              {
                charTimeStart = rtc.getUnixTime(rtc.getTime());
                if (displacement)
                {
                  lcd.setCursor(0, 3);
                }
                else
                {
                  lcd.setCursor(0, 3);
                }
                lcd.write(byte(0));
                characterVisible = true;
              }
            }
            else
            {
              charTimeEnd = rtc.getUnixTime(rtc.getTime());
              if ((charTimeEnd - charTimeStart) >= 1)
              {
                if (displacement)
                {
                  lcd.setCursor(0, 3);
                }
                else
                {
                  lcd.setCursor(0, 3);
                }
                lcd.print(" ");
                characterVisible = false;
              }
            }
            break;
          }       
  }
}


/***********************************************************************************************************
 * FUNCTION NAME :- getEncoderMovement
 * USAGE         :- This Function Tracks the Rotory Encoder Movement and according to ClockPin,  
 *                  decides the desired output with microcontroller.
 ***********************************************************************************************************/
int getEncoderMovement()
{
  static int aLastState = HIGH;   // a is related to clkPin
  static int bLastState = HIGH;   // b is related to clkPin
  int movement = 0;

  int aNewState = digitalRead(clkPin);
  int bNewState = digitalRead(dataPin);
  if ((aNewState != aLastState) || (bNewState != bLastState))
  {
    if (aLastState == HIGH && aNewState == LOW)
    {
      movement = (bLastState * 2 - 1);    // Movement will be either 1 or -1, according to the value of bLastState.
    }
  }
  aLastState = aNewState;
  bLastState = bNewState;
  return movement;
}


/***********************************************************************************************************
 * FUNCTION NAME :- showSetChoice
 * USAGE         :- This Function shows the choice setting what user want to set.
 *                  e.g. under menuChoice, there are several settings, it deals with it.
 ***********************************************************************************************************/
void showSetChoice ()
{
  switch (menuChoice)
  {
    case 1:
          {
            if (oneTwoPulse)
            {
              lcd.setCursor(5, 0);
              lcd.print(firstPulse);
              lcd.setCursor(14, 0);
              lcd.print(secondPulse);
            }
            else
            {
              lcd.setCursor(0, 0);
              lcd.print("SET");
              lcd.setCursor(4, 0);
              lcd.print(" Pulse: ");
              lcd.print(pulseLength);
              lcd.print("ms");
            }
            break;
          }

          
    case 2:
          {
            lcd.setCursor(12, 1);  // Erasing extra characters from one-two pulse (if any)
            lcd.print("      ");
            lcd.setCursor(0, 1);
            lcd.print("SET");
            lcd.setCursor(4, 1);
            lcd.print(" ");

            if (pulses != 0)
            {
              lcd.print(pulses);
              
              if (pulses > 1)
              {
                lcd.print(" Pulses");
              }
              else if (pulses == 1)
              {
                lcd.print(" Pulse");
              }
            }
            else
            {
              lcd.print("One-Two Pulse");
            }
            break;
          }


    case 3:
          {
            lcd.setCursor(0, 2);
            lcd.print("SET");
            lcd.setCursor(4, 2);
            lcd.print(" Delay: ");
            lcd.print(delayBetweenPulses);
            lcd.print("ms");
          }
  }
}


/***********************************************************************************************************
 * FUNCTION NAME :- correctDisplay
 * USAGE         :- Corrects what the LCD Displays, 
 *                  e.g. when a variable changes from 100ms to 95ms, the LCD displays 95ms. 
 *                  This functiion corrects that.
 ***********************************************************************************************************/
void correctDisplay ()
{
  // TO DO :- Correct Display for ONE-TWO Pulse.
  if (oneTwoPulse)
  {
    if ((firstPulse == 1) || (firstPulse == 9))
    {
      lcd.setCursor(6 , 0);
      lcd.print("   ");
    }
    else if (firstPulse == 95)
    {
      lcd.setCursor(7, 0);
      lcd.print(" ");
    }
    else if (firstPulse == 995)
    {
      lcd.setCursor(8, 0);
      lcd.print(" ");
    }

    if ((secondPulse == 1) || (secondPulse == 9))
    {
      lcd.setCursor(15 , 0);
      lcd.print("   ");
    }
    else if (secondPulse == 95)
    {
      lcd.setCursor(16, 0);
      lcd.print(" ");
    }
    else if (secondPulse == 995)
    {
      lcd.setCursor(17, 0);
      lcd.print(" ");
    }
    return;
  }

  if ((pulseLength == 1) || (pulseLength == 9))
  {
    // Asthetic Changes
    lcd.setCursor(15, 0);
    lcd.print("     ");
  }
  else if (pulseLength == 95)
  {
    lcd.setCursor(16, 0);
    lcd.print(" ");
  }
  else if (pulseLength == 995)
  {
    lcd.setCursor(17, 0);
    lcd.print(" ");
  }
  else if (pulseLength == 9995)
  {
    lcd.setCursor(18, 0);
    lcd.print(" ");
  }
  else if (pulseLength == 99995)
  {
    lcd.setCursor(19, 0);
    lcd.print(" ");
  }

  if (pulses == 1)
  {
    lcd.setCursor(12, 1);
    lcd.print(" ");
  }

  if (delayBetweenPulses == 50)
  {
    lcd.setCursor(16 , 2);
    lcd.print(" ");
  }
}

// *********************** THE END OF CODE FOR SPOT WELDER **************************** //
// *********************** This code is written By Mr. Anukesh Anil Ambatkar ***********************//

please help us maintain the forum tidy and help you by using code tags when posting code.

Edit your post using the :pencil2: in the tool bar just below your post

select the code part and press the <code/> icon in the tool bar to mark it as code. (also make sure you indented the code in the IDE before copying, that’s done by pressing ctrlT on a PC or cmdT on a Mac)

➜ please read How to get the best out of this forum

1 Like

edit your post. mark entire sketch and press "code"-tag. then press "save post"

hi,
i have update the code part.
here, issue is -->
after uploading code to Arduino, weldOutput goes high and relay triggers even if weldBtn is not connected.

thx

do you have external pullup or pulldown resistors for the button?

yes i have done with this now

button is not connected yet
tried with small push switch with 10k resistor, but not working

Are you using a resistor to pull Pin 13 LOW for when the button is not pressed?

i have tried with 10k resistor in series with push switch and connected to pin 13 and GND.

Make a small sketch and use Serial.println(digitalRead(weldBtn)); to monitor the pin, which should be LOW when not pressed.

const int weldBtn = 13;  

void setup() {
  Serial.begin(115200);
  pinMode(weldBtn, INPUT);
}

void loop() {
  Serial.println(digitalRead(weldBtn));
}

yes, it is printing output as 0 i.e. low on serial monitor when button is not connected

can you please let me know about connections of pullup or pulldown resistors?

after adding pullup resistor, it is working fine
Thank you so much Jackson, kolaha and xfpd for your support

Great - well done on finding out what was needed

(You could use the INPUT_PULLUP mode of your pin and not need the external resistor)

1 Like

i still trying to understand what is DS3231 for. is this device a clock when welder not used?

yes kolaha,
we can ignore the DS3231 if not required

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.