#include #include #include #include #include LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); Servo myServo; //Pins assigned //Const Variables const byte TRIAC = 3; //Load Output const byte rdy = 4; const byte bzr = 7; const int buttonPin = 9; const byte servoPin = 10; const int PinB = 12; const int PinA = 13; const int noEvent = 0; const int shortPress = 1; const int longPress = 2; const int longerPress = 3; const int tgr_dly = 5084; //delay after zero cross at peak sine - average of 50/60Hz const int shortTime = 500; //if equal longTime there is no unrecorded press const int longTime = 500; const int longerTime = 2000; const int pause = 450; // pause value after First Weldconst byte ServoPot2 = A0; // Servo End preset const byte ServoPot2 = A0; const byte ServoPot1 = A1; // Servo Start preset const byte Pot = A2; // POT Weld Value // SCL is A5 // SDA is A4 //Variables int pinAState = LOW; int PinALastState = LOW; int Counter1 = 0; int prevRotaryVal; int PreWeldAddr = 120; // Address block to store PreWeld time int startSrvAddr = 130; // Address block to store servo Start degree int endSrvAddr = 140; // Address block to store servo end degree int pre; int SrvPotMap1 = 0 ; int SrvPotMap2 = 0 ; int counter = 0; // continous weld counter int WeldStepValue = 10; // Value of POT in milliseconds int OldWeldStepValue; // Old value of POT int PotValue; // Actual POT value int ConfigureVal; byte zCd = 2; // Zero Crossing Detect byte previousButtonState = HIGH; byte buttonState = HIGH; byte zCdState; unsigned long buttonPressStartTimeStamp; unsigned long buttonPressDuration; unsigned long timeCheck = 1000; // time to check zero cross error unsigned long backLightStart; // capture current time unsigned long backLightOff = 60000; // timeout LCD backlight unsigned long previousTime; // The last time the backlight was on unsigned long currentMillis; boolean startTimeout = false; // zc sense error timeout volatile boolean zeroCrossingFlag = false; void setup() { pre = EEPROM.read(PreWeldAddr); SrvPotMap1 = EEPROM.read(endSrvAddr); SrvPotMap2 = EEPROM.read(startSrvAddr); pinMode (PinA, INPUT_PULLUP); pinMode (PinB, INPUT_PULLUP); pinMode(Pot, INPUT); pinMode(ServoPot1, INPUT); pinMode(ServoPot2, INPUT); pinMode(servoPin, OUTPUT); pinMode(TRIAC, OUTPUT); pinMode(rdy, OUTPUT); pinMode(bzr, OUTPUT); pinMode(zCd, INPUT_PULLUP); pinMode(buttonPin, INPUT_PULLUP); attachInterrupt(0, setFlag, FALLING);//zero cross attachPCINT(digitalPinToPCINT(13), rotaryEncoder, CHANGE); lcd.clear(); lcd.begin(20, 4); lcd.setCursor(5, 0); lcd.print("Spot Welder"); lcd.setCursor(3, 1); lcd.print("Microcontroller"); lcd.setCursor(4, 3); lcd.print("Version 2.0"); delay(2000); lcd.clear(); lcd.setCursor(0, 2); lcd.print("Design"); lcd.setCursor(1, 3); lcd.print("A.George Thomas"); delay(2000); lcd.clear(); Display(); //Serial.begin(9600); } void loop() { unsigned long startTime = millis(); // start timer for LCD time-out while (!zeroCrossingFlag && (millis() - startTime < timeCheck)) { /* hang inside while loop until either zeroCrossFlag or timeout occurs both conditions need to be met to stay in while loop */ } if (zeroCrossingFlag)//exit while loop due to flag set { digitalWrite(rdy, HIGH); lcd.setCursor(9, 3); lcd.print("*READY*"); zeroCrossingFlag = false; } else //exit while loop due to time out error { Serial.println("ZC Sense ERROR"); lcd.setCursor (0, 2); lcd.print("ZC Sense Error "); digitalWrite(rdy, HIGH); delay(50); digitalWrite(rdy, LOW); delay(100); digitalWrite(rdy, HIGH); delay(50); digitalWrite(rdy, LOW); delay(500); } lcd.setCursor(0, 3); lcd.print("W2:"); lcd.print(rotaryEncoder()); lcd.print("ms "); //Start debug /*if (OldWeldStepValue != WeldStep()) { lcd.backlight(); Serial.print("Set weld time(W2): "); Serial.print(WeldStep()); Serial.println("ms"); OldWeldStepValue = WeldStep(); digitalWrite(bzr, HIGH); delay(3); digitalWrite(bzr, LOW); }*/ //end debug backLightStart = millis(); if (backLightStart - previousTime >= backLightOff) { previousTime = backLightStart; lcd.noBacklight(); } switch (checkButton()) { case shortPress: lcd.clear(); lcd.setCursor(0, 0); lcd.print("Mode: Manual Weld "); lcd.setCursor(0, 2); lcd.print("W1:"); lcd.print(pre); //lcd.print(char(0xE4)); lcd.print("ms"); lcd.setCursor(9, 2); lcd.print("P:"); lcd.print(pause); lcd.print("ms"); lcd.setCursor(0, 3); lcd.print("W2:"); lcd.print(rotaryEncoder()); lcd.print("ms "); lcd.backlight(); Weld(); break; case longPress: lcd.clear(); lcd.setCursor(0, 0); lcd.print("Mode: Automatic Weld"); continousWeld(); break; case longerPress: lcd.clear(); lcd.setCursor(1, 0); lcd.print("CONFIGURATION MODE"); SetWeldHead(); break; } zeroCrossingFlag = false; } void Display() { lcd.clear(); lcd.setCursor(5, 0); lcd.print("Spot Welder"); lcd.setCursor(3, 1); lcd.print("Microcontroller"); lcd.setCursor(0, 2); lcd.print("W1:"); lcd.print(pre); //lcd.print(char(0xE4)); lcd.print("ms"); lcd.setCursor(9, 2); lcd.print("P:"); lcd.print(pause); lcd.print("ms"); lcd.setCursor(0, 3); lcd.print("W2:"); lcd.print(rotaryEncoder()*2); lcd.print("ms "); myServo.detach(); } int rotaryEncoder() { pinAState = digitalRead(PinA); if (pinAState != PinALastState) { if (digitalRead(PinB) != pinAState) { Counter1++; } else { Counter1--; } Serial.println(Counter1 >> 1); } PinALastState = pinAState; if (Counter1 >= 500) { Counter1 = 500; } if (Counter1 <= 0) { Counter1 = 0; } return ((Counter1 >> 1)*2); } /*int WeldStep() // Map POT value from A2 to increments of 20 from 0 to 500 { int PrevVal = 0; PotValue = analogRead(Pot); WeldStepValue = (map(PotValue, 0, 1023, 0, 50)) * 20; // Zero value disables W2 if (WeldStepValue < 10) { WeldStepValue = 0; } if (WeldStepValue >= 500) { WeldStepValue = 500; } else { WeldStepValue = WeldStepValue; } return WeldStepValue; }*/ void Weld() //Actual weld { int wait; if ((SrvPotMap1 && SrvPotMap2) == 0) //disables servo when both servo pot values are zero and sets weld interval { wait = 700; } else { wait = 0; } delay(wait); lcd.backlight(); myServo.attach(servoPin); digitalWrite(rdy, LOW); ServoStart(); buttonState = digitalRead(buttonPin); zeroCrossingFlag = false; //set flag false and wait for next zero crossing while (!zeroCrossingFlag) {}; delayMicroseconds(tgr_dly); digitalWrite(TRIAC, HIGH); delay(pre); //preWeld time ms digitalWrite(TRIAC, LOW); delay(pause); zeroCrossingFlag = false; //set flag false and wait for next zero crossing while (!zeroCrossingFlag) {}; delayMicroseconds(tgr_dly); digitalWrite(TRIAC, HIGH); delay(rotaryEncoder()); digitalWrite(TRIAC, LOW); ServoReturn(); myServo.detach(); digitalWrite(bzr, HIGH); delay(100); digitalWrite(bzr, LOW); } void continousWeld() { int countWeldCycle; int bzrCount; lcd.backlight(); lcd.setCursor(0, 1); lcd.print("W1:"); lcd.print(pre); lcd.print("ms "); //lcd.print(char(0xE4)); //lcd.print("s"); lcd.setCursor(9, 1); lcd.print("W2:"); lcd.print(rotaryEncoder()); lcd.print("ms"); while (bzrCount < 2) { digitalWrite(bzr, HIGH); delay(60); digitalWrite(bzr, LOW); delay(60); bzrCount++; } buttonState = digitalRead(buttonPin); while (buttonState == HIGH) { countWeldCycle++; lcd.setCursor(0, 3); lcd.print("Weld Cycle(s):"); lcd.print(countWeldCycle); delay(100); buttonState = digitalRead(buttonPin); Weld(); delay(500); } digitalWrite(bzr, HIGH); Display(); lcd.backlight(); delay(200); digitalWrite(bzr, LOW); delay(200); } ///////////////////////// BEGIN CONFIGURAION MODE /////////////////////////////////// void SetWeldHead() // Set start and end Weld Head height. { int bzrCount = 0; lcd.backlight(); digitalWrite(rdy, LOW); while (bzrCount < 5) { digitalWrite(bzr, HIGH); delay(50); digitalWrite(bzr, LOW); delay(50); bzrCount++; } buttonState = digitalRead(buttonPin); while (buttonState == HIGH) { int enable; int preSrvPotMap2; int startSrv = map(analogRead(ServoPot2), 0, 1023, 0, 130); ConfigureVal = map(analogRead(Pot), 0, 1023, 1, 4); if (ConfigureVal == 1) { menu1: if (startSrv < 25) { startSrv = 0; } lcd.setCursor(0, 1); lcd.print(ConfigureVal); lcd.setCursor(1, 1); lcd.print("-Set Start Point "); myServo.attach(servoPin); myServo.write(startSrv); lcd.setCursor(3, 2); lcd.print("Set start:"); lcd.print(startSrv); lcd.print(char(223)); lcd.setCursor(3, 3); lcd.print("Stored :"); lcd.print(SrvPotMap2); lcd.print(char(223)); if ((digitalRead(buttonPin) == LOW) && SrvPotMap2 != startSrv) // Display message only if current value is different from the stored value { SrvPotMap2 = startSrv; EEPROM.update(startSrvAddr, startSrv); lcd.setCursor(0, 2); lcd.clear(); lcd.setCursor(2, 2); lcd.print("SAVE SUCCESSFULL"); lcd.setCursor(0, 3); lcd.print("value changed: "); lcd.print(startSrv); lcd.print(char(223)); digitalWrite(bzr, HIGH); delay(100); digitalWrite(bzr, LOW); delay(100); digitalWrite(bzr, LOW); delay(3000); lcd.clear(); lcd.setCursor(1, 0); lcd.print("CONFIGURATION MODE"); goto menu1; } } if (ConfigureVal == 2) { menu2: int endSrv = map(analogRead(ServoPot1), 0, 1023, 0, 120); if (endSrv < 25) { endSrv = 0; } lcd.setCursor(0, 1); lcd.print(ConfigureVal); lcd.setCursor(1, 1); lcd.print("-Set End Point "); myServo.attach(servoPin); myServo.write(endSrv); lcd.setCursor(0, 2); lcd.print(" Set end:"); lcd.print(endSrv); lcd.print(char(223)); lcd.print(" "); lcd.setCursor(0, 3); lcd.print(" Stored :"); lcd.print(SrvPotMap1); lcd.print(char(223)); lcd.print(" "); if ((digitalRead(buttonPin) == LOW) && SrvPotMap1 != endSrv) // Display message only if stored value is different from the current value { SrvPotMap1 = endSrv; EEPROM.update(endSrvAddr, endSrv); lcd.clear(); lcd.setCursor(2, 2); lcd.print("SAVE SUCCESSFULL"); lcd.setCursor(0, 3); lcd.print("value changed: "); lcd.print(endSrv); lcd.print(char(223)); lcd.print(" "); digitalWrite(bzr, HIGH); delay(100); digitalWrite(bzr, LOW); delay(50); digitalWrite(bzr, LOW); delay(3000); lcd.clear(); lcd.setCursor(1, 0); lcd.print("CONFIGURATION MODE"); goto menu2; } enable = 1; } if ((ConfigureVal == 3) && enable == 1) { myServo.detach(); lcd.setCursor(1, 0); lcd.print("CONFIGURATION MODE"); lcd.setCursor(0, 1); lcd.print(ConfigureVal); lcd.print("-Test Head Height"); if (digitalRead(buttonPin) == LOW) { myServo.attach(servoPin); lcd.setCursor(0, 2); lcd.print("Start Point : "); lcd.print(SrvPotMap2); lcd.print(" *"); lcd.setCursor(0, 3); lcd.print("End Point : "); lcd.print(SrvPotMap1); lcd.print(" "); ServoStart(); delay(1000); ServoReturn(); lcd.setCursor(0, 2); lcd.print("Start Point : "); lcd.print(SrvPotMap2); lcd.print(" "); lcd.setCursor(0, 3); lcd.print("End Point : "); lcd.print(SrvPotMap1); lcd.print(" *"); myServo.detach(); } } if (ConfigureVal == 4) { menu4: enable = 0; int w1Value; w1Value = map(analogRead(ServoPot1), 0, 1023, 0, 10); if (w1Value < 1) { w1Value = 0; } lcd.setCursor(0, 1); lcd.print(ConfigureVal); lcd.print("-Set Pre-weld time "); lcd.setCursor(0, 2); lcd.print("Set W1 :"); lcd.print(w1Value); //lcd.print(char(0xE4)); lcd.print("ms "); lcd.setCursor(0, 3); lcd.print("W1 Stored:"); lcd.print(pre); //lcd.print(char(0xE4)); lcd.print("ms "); if ((digitalRead(buttonPin) == LOW) && pre != w1Value) // Save to EEPROM only if stored value is different from the current value { pre = w1Value; EEPROM.update(PreWeldAddr, pre); lcd.clear(); lcd.setCursor(2, 0); lcd.print("SAVE SUCESSFULL"); lcd.setCursor(0, 1); lcd.print("W1 changed to "); lcd.print(pre); lcd.print("ms "); //lcd.print(char(0xE4)); digitalWrite(bzr, HIGH); delay(100); digitalWrite(bzr, LOW); delay(3000); lcd.setCursor(1, 0); lcd.print("CONFIGURATION MODE"); goto menu4; } } if (digitalRead(buttonPin) == LOW) { lcd.backlight(); Display(); break; } } } //////////////////////// END CONFIGURATION MODE //////////////////////// void setFlag() { zeroCrossingFlag = true; //interrupt sets flag true } void ServoStart() // Increments to start position from Finish { for (int i = SrvPotMap1; i <= SrvPotMap2; i += 1) { myServo.attach(servoPin); myServo.write(i); delay(10); } } void ServoReturn() // Increments to Finish position from Start { for (int i = SrvPotMap2; i >= SrvPotMap1; i -= 1) { myServo.write(i); delay(10); } } byte checkButton() { byte event = noEvent; buttonState = digitalRead(buttonPin); //button pressed if (buttonState == LOW && previousButtonState == HIGH) { delay(20); //blocking debounce routine buttonState = digitalRead(buttonPin);//read button again if (buttonState == LOW && previousButtonState == HIGH) { buttonPressStartTimeStamp = millis(); startTimeout = true; } } //button released if (buttonState == HIGH && previousButtonState == LOW) { delay(20);//blocking debounce routine buttonState = digitalRead(buttonPin);//read button again if (buttonState == HIGH && previousButtonState == LOW) { buttonPressDuration = (millis() - buttonPressStartTimeStamp); startTimeout = false;//duration determined no timeout required } } if (buttonPressDuration > 0 && buttonPressDuration <= shortTime) { event = shortPress; buttonPressDuration = 0; } if (buttonPressDuration > longTime && buttonPressDuration <= longerTime) { event = longPress; buttonPressDuration = 0; } //button not released and still timing if (buttonState == LOW && startTimeout == true && (millis() - buttonPressStartTimeStamp) > longerTime) { event = longerPress; startTimeout = false; } buttonPressDuration = 0; previousButtonState = buttonState; return event; }