#include #include #include #include #include #include #include #include hd44780_I2Cexp lcd; Servo myServo; // Const Variables and pin assinged const byte ENC_SW = 3; // Encoder Switch const byte rdy = 4; // READY LED const byte servoPin = 6; // Servo const int ENC_PinA = 7; // PIN A of Encoder const byte bzr = 5; // Buzzer const int ENC_PinB = 8; // PIN B of Encoder const int buttonPin = 9; // Weld button const byte cs = 10; // Contact Sense const int TRIAC = A1; // Load 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 = 200; // if equal longTime there is no unrecorded press const int longTime = 500; const int longerTime = 2000; const int pause = 450; // pause value between dual pulses const int delayTime = 50; // bounce delay for Encoder Switch // Variables #define Temp A6 // NTC PIN #define RR 10000 // Reference Resistance #define NR 10000 // Nominal Resistance #define NT 25 // Nominal Temperature #define B_Val 3435 NTC_Thermistor *thermistor; byte zCd = 2; // Zero Crossing Detect //byte weldCont = false; byte menuSelect = 0; byte stayInMenu = false; byte weldExitFlag = true; byte previousButtonState = HIGH; byte buttonState = HIGH; byte prevENC_SWstate = HIGH; byte ENC_SWstate = HIGH; byte buttonFlag; //byte resetFlag = false; byte manualWeld = 0; byte testLoop = 1; byte cs_State = HIGH; byte prevCS_State; byte currCS_State; byte confMenu; byte rdyState; byte noCtc; byte ctc; byte currCtc; byte prevCtc; byte prevWeldFlag; int ENC_PinAState = LOW; int ENC_PinALastState = LOW; int WeldTime = 30; // read value from rotaryEncoder() int prevRotaryVal; int W2Addr = 110; // Address block to store W2 value 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 SrvPotMap1; int SrvPotMap2; int counter; // Auto weld counter int WeldStepValue; // Value of POT in milliseconds int OldWeldStepValue; // Old value of POT int PotValue; // Actual POT value int ConfigureVal; int w1Value = 10; int pValue = 50; int select; int Counter1; int Counter; unsigned long TimeStamp; unsigned long ENC_SWpressDuration; unsigned long buttonPressStartTimeStamp; unsigned long buttonPressDuration; unsigned long timeCheck = 1000; // time to check zero cross error unsigned long currentMillis; unsigned long prevMillis; unsigned long prevT; unsigned long currT; unsigned long delayT = 500; boolean startTimeout = false; // zc sense error timeout volatile boolean zeroCrossingFlag = false; void setup() { lcd.clear(); lcd.begin(16, 2); thermistor = new NTC_Thermistor(Temp, RR, NR, NT, B_Val); ServoReturn(); //w1Value = EEPROM.read(PreWeldAddr); SrvPotMap1 = EEPROM.read(endSrvAddr); SrvPotMap2 = EEPROM.read(startSrvAddr); //WeldTime = EEPROM.read(W2Addr); pinMode(buttonPin, INPUT_PULLUP); pinMode(ENC_PinA, INPUT_PULLUP); pinMode(ENC_PinB, INPUT_PULLUP); pinMode(zCd, INPUT_PULLUP); pinMode(cs, INPUT_PULLUP); pinMode(ENC_SW, INPUT_PULLUP); pinMode(servoPin, OUTPUT); pinMode(TRIAC, OUTPUT); pinMode(rdy, OUTPUT); pinMode(bzr, OUTPUT); pinMode(A2, INPUT); pinMode(A4, INPUT_PULLUP); pinMode(A5, INPUT_PULLUP); attachInterrupt(0, setFlag, FALLING); // zero cross attachPCINT(digitalPinToPCINT(ENC_PinA), rotaryEncoder, CHANGE); //attachPCINT(digitalPinToPCINT(ENC_SW), resetENC, RISING); attachPCINT(digitalPinToPCINT(buttonPin), WeldExit, CHANGE); delay(10); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Max Weld"); lcd.setCursor(12, 0); lcd.print("v3.0"); lcd.setCursor(0, 1); lcd.print("GT Designs"); delay(2000); lcd.clear(); Display(); startupTone(); Serial.begin(115200); } // ------------------------------------------------ FUNCTIONS --------------------------------- void startupTone() { tone(bzr, 2500); delay(120); noTone(bzr); delay(240); tone(bzr, 2500); delay(120); noTone(bzr); } void weldTone() { if (manualWeld == 0) { tone(bzr, 2322); delay(70); noTone(bzr); tone(bzr, 2222); delay(70); noTone(bzr); } else { tone(bzr, 3153); delay(50); noTone(bzr); } } void saveSuccess() { pinMode(bzr, OUTPUT); tone(bzr, 2025); delay(300); noTone(bzr); } /*void resetENC() { if (resetFlag == false) { Counter1 = 0; } }*/ void Display() { lcd.clear(); lcd.setCursor(1, 0); lcd.print("W1:"); lcd.print(w1Value); myServo.detach(); } void rotaryEncoder() { ENC_PinAState = digitalRead(ENC_PinA); if (digitalRead(ENC_PinB) != ENC_PinAState) { Counter1--; } else { Counter1++; } } int readEncoder() { noInterrupts(); int copyCounter = Counter1; interrupts(); return (copyCounter) >> 1; } void Weld() // Actual weld { delay(300); 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(w1Value); // 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(WeldTime); digitalWrite(TRIAC, LOW); ServoReturn(); myServo.detach(); weldTone(); lcd.clear(); } void aWeld() // Auto weld { if (currCtc == 0 && prevCtc == 1) { //Serial.println(currCtc); //Serial.println(prevCtc); //Serial.println(" "); prevCtc = currCtc; //Serial.println(currCtc); //Serial.println(prevCtc); //Serial.println(" "); myServo.attach(servoPin); digitalWrite(rdy, LOW); ServoStart(); zeroCrossingFlag = false; // set flag false and wait for next zero crossing while (!zeroCrossingFlag) { }; delayMicroseconds(tgr_dly); digitalWrite(TRIAC, HIGH); delay(w1Value); // 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(WeldTime); digitalWrite(TRIAC, LOW); } ServoReturn(); myServo.detach(); weldTone(); } void WeldExit() // Interrupt to exit Auto Weld { weldExitFlag = true; } 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(5); } } void ServoReturn() // Increments to Finish position from Start { for (int i = SrvPotMap2; i >= SrvPotMap1; i -= 1) { myServo.write(i); delay(5); } } int clearSelectPointer(int checkPointer) { switch (checkPointer) { case 1: // for select 1 lcd.setCursor(0, 1); // 2 lcd.print(" "); lcd.setCursor(8, 1); // 3 lcd.print(" "); break; case 2: // for select 2 lcd.setCursor(0, 0); // 1 lcd.print(" "); lcd.setCursor(8, 1); // 3 lcd.print(" "); break; case 3: // for select 3 lcd.setCursor(0, 0); // 1 lcd.print(" "); lcd.setCursor(0, 1); // 2 lcd.print(" "); break; case 4: lcd.setCursor(0, 0); // 1 lcd.print(" "); lcd.setCursor(0, 1); // 2 lcd.print(" "); lcd.setCursor(8, 1); //3 lcd.print(" "); break; } return (checkPointer); } // ------------------------------------------------ END OF FUNCTIONS -------------------------- void loop() { 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 */ } lcd.setCursor(1, 0); lcd.print("W1:"); lcd.print(w1Value); lcd.setCursor(1, 1); lcd.print("W2:"); lcd.print(WeldTime); lcd.setCursor(9, 0); lcd.print("T:"); lcd.print(String(thermistor->readCelsius())); lcd.setCursor(9, 1); lcd.print("P:"); digitalWrite(rdy, HIGH); ENC_SWstate = digitalRead(ENC_SW); if (ENC_SWstate != prevENC_SWstate) { if (ENC_SWstate == LOW) { Counter1 = w1Value / 10 << 1; Counter++; confMenu = 1; /* Serial.print("Pass:"); Serial.println(Counter); Serial.print("Counter:"); Serial.println(Counter1); Serial.print("W1:"); Serial.println(w1Value); Serial.print("W2:"); Serial.println(WeldTime); Serial.print("pValue:"); Serial.println(pValue);*/ } } prevENC_SWstate = ENC_SWstate; while (confMenu == 1) { ENC_SWstate = digitalRead(ENC_SW); if (ENC_SWstate != prevENC_SWstate) { if (ENC_SWstate == LOW) { select += 1; select = select % 4; /*Serial.print("Select:"); Serial.println(select); Serial.println(" ");*/ if (select == 0) { noInterrupts(); Counter1 = w1Value / 10 << 1; interrupts(); } if (select == 1) { noInterrupts(); Counter1 = WeldTime / 10 << 1; interrupts(); } if (select == 2) { noInterrupts(); Counter1 = pValue / 10 << 1; interrupts(); } } prevENC_SWstate = ENC_SWstate; } switch (select) { case 0: //W1 clearSelectPointer(1); lcd.setCursor(0, 0); lcd.print(">"); w1Value = readEncoder() % 6 * 10; if (w1Value <= 0) { w1Value = 0; } lcd.setCursor(1, 0); lcd.print("W1:"); lcd.print(w1Value); lcd.print(" "); break; case 1: //W2 clearSelectPointer(2); lcd.setCursor(0, 1); lcd.print(">"); WeldTime = readEncoder() % 51 * 10; if (WeldTime <= 0) { WeldTime = 0; } lcd.setCursor(1, 1); lcd.print("W2:"); lcd.print(WeldTime); //lcd.setCursor(5, 1); lcd.print(" "); break; case 2: //P clearSelectPointer(3); lcd.setCursor(8, 1); lcd.print(">"); pValue = readEncoder() % 11 * 10; if (pValue <= 0) { pValue = 0; } lcd.setCursor(9, 1); lcd.print("P:"); lcd.print(pValue); lcd.print("%"); lcd.print(" "); break; default: clearSelectPointer(4); confMenu = 0; select = 0; break; } } while (weldExitFlag == false) // begin Auto Weld { zeroCrossingFlag = false; while (!zeroCrossingFlag) { }; delayMicroseconds(8600); // Sense voltage (after zero cross). higher number, lower voltage. digitalWrite(TRIAC, HIGH); delayMicroseconds(200); digitalWrite(TRIAC, LOW); cs_State = digitalRead(cs); currCS_State = cs_State; if (currCS_State == prevCS_State) { ctc = 0; } else { ctc = 1; } prevCS_State = currCS_State; currCtc = ctc; if (currCtc != prevCtc) { if (currCtc == LOW && prevCtc == HIGH) { delay(300); aWeld(); } prevCtc = currCtc; } buttonState = digitalRead(buttonState); previousButtonState = buttonState; currCtc = prevCtc; } // End Auto weld if (zeroCrossingFlag) // exit while loop due to flag set { zeroCrossingFlag = false; } switch (checkButton()) { case shortPress: lcd.clear(); lcd.print("Welding...."); Weld(); break; case longPress: lcd.clear(); lcd.setCursor(0, 0); lcd.print("Auto Weld"); delay(800); lcd.clear(); weldExitFlag = false; break; case longerPress: break; } } // end of Loop byte checkButton() { byte event = 0; 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; previousButtonState = buttonState; } // button not released and still timing if (buttonState == LOW && startTimeout == true && (millis() - buttonPressStartTimeStamp) > longerTime) { event = longerPress; digitalWrite(rdy, LOW); startTimeout = false; } buttonPressDuration = 0; previousButtonState = buttonState; prevENC_SWstate = ENC_SWstate; return event; }