From 8d1700651e1090e6bf94f5c4310972337b57825b Mon Sep 17 00:00:00 2001 From: candidol <31170621+candidol@users.noreply.github.com> Date: Mon, 21 Aug 2017 22:37:49 +0100 Subject: [PATCH 01/19] Add files via upload --- Classes.ino | 18 ++++++---- Definitions.h | 20 ++++++----- Eeprom.ino | 5 +-- Functions.ino | 28 +++++++++++---- README.md | 6 ++++ Spotwelder-6.2.ino | 90 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 144 insertions(+), 23 deletions(-) create mode 100644 Spotwelder-6.2.ino diff --git a/Classes.ino b/Classes.ino index a57ca80..b2d2eb2 100644 --- a/Classes.ino +++ b/Classes.ino @@ -48,20 +48,24 @@ void Menu::displayAll() displayName(upDownItemNr, menuItems[upDownItemNr].name); menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, 0); } - upDownItemNr.value=0; + upDownItemNr.value = 0; menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, 0); // item 0 has focus displayDot(0); drawColorTextLine(10, 0, "- + sel weld", COLOR_YELLOW, COLOR_BLUEVIOLET); + // drawColorTextLine(10, 0, "Weld Sel Up Down", COLOR_YELLOW, COLOR_BLUEVIOLET); } else { drawColorTextLine(4, 0, " Continuously", COLOR_WHITE, COLOR_RED); drawColorTextLine(5, 0, " mode", COLOR_WHITE, COLOR_RED); drawColorTextLine(6, 0, " Take care!", COLOR_WHITE, COLOR_RED); + // drawColorTextLine(10, 0, "Weld ", COLOR_YELLOW, COLOR_BLUEVIOLET); + drawColorTextLine(10, 0, " Weld", COLOR_YELLOW, COLOR_BLUEVIOLET); } } void Menu::displayDot(bool on) -{ tft.fillCircle(87, 170, 12, on? COLOR_WHITE : COLOR_DARKBLUE); +// { tft.fillCircle(87, 170, 12, on? COLOR_WHITE : COLOR_DARKBLUE); +{ tft.fillCircle(87, 170, 12, on? COLOR_RED : COLOR_DARKGREEN); } void Menu::displayName(int upDownItemNr, String &name) @@ -70,8 +74,8 @@ void Menu::displayName(int upDownItemNr, String &name) void Menu::displayValue(int upDownItemNr, int value, bool focus, bool background) { menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(" ")); // clear line - menu.drawColorTextLine(2*upDownItemNr+1, 0, focus? ">" : " ", TXT_COLOR); - menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(value), background? COLOR_BLACK : TXT_COLOR, background? COLOR_CYAN : COLOR_BLACK); + menu.drawColorTextLine(2*upDownItemNr+1, 0, focus? ">" : " ", TXT_COLOR1); + menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(value), background? COLOR_BLACK : TXT_COLOR1, background? COLOR_CYAN : COLOR_BLACK); } // --------------------------------------------------------------------------- @@ -82,11 +86,13 @@ value(value), step(step), minValue(minValue), maxValue(maxValue) } int UpDownValue::up() { value += step; - return value = min(max(value, minValue), maxValue); + // return value = min(max(value, minValue), maxValue); + return value = (value > maxValue) ? minValue : value; } int UpDownValue::down() { value -= step; - return value = min(max(value, minValue), maxValue); + // return value = min(max(value, minValue), maxValue); + return value = (value < minValue ) ? maxValue : value; } UpDownValue::operator int() // conversion operator, object returns value diff --git a/Definitions.h b/Definitions.h index 69dc7db..32522ba 100644 --- a/Definitions.h +++ b/Definitions.h @@ -6,24 +6,26 @@ const byte BCDswitch1pin = 7; const byte BCDswitch2pin = 6; const byte BCDswitch3pin = 5; const byte weldPin = 2; -const byte weldButtonPin = 4; -const byte upButtonPin = 7; -const byte downButtonPin = 8; -const byte selectButtonPin = 6; +const byte weldButtonPin = 4; +const byte upButtonPin = 7; +const byte downButtonPin = 8; +const byte selectButtonPin = 6; const byte ledPin = 12; -const byte zeroCrossPin = 3; +const byte zeroCrossPin = 3; const byte tftJumperOutPin = A5; const byte tftJumperInPin = A4; -const byte TFT_RSTpin = 9; -const byte TFT_RSpin = 10; -const byte TFT_CSpin = 5; +const byte TFT_RSTpin = 9; +const byte TFT_RSpin = 10; +const byte TFT_CSpin = 5; //const byte TFT_CLKpin = 13; // for SW SDI, doesn't work //const byte TFT_SDIpin = 11; // for SW SDI, doesn't work const int step_ms = 50; -const int sinusMax_us = 4583; +// const int sinusMax_us = 4583; +const int sinusMax_us = 5000; #define TXT_COLOR COLOR_YELLOW +#define TXT_COLOR1 COLOR_SNOW #endif diff --git a/Eeprom.ino b/Eeprom.ino index a23ddef..31d0541 100644 --- a/Eeprom.ino +++ b/Eeprom.ino @@ -1,5 +1,6 @@ -const unsigned maxWrites = 100; -const unsigned initValue = 12341; // take another value for new initialization +const unsigned maxWrites = 100; +// const unsigned initValue = 123456; // take another value for new initialization +const uint16_t initValue = 12345; // take another value for new initialization void Eeprom::init() { setMemPool(0, EEPROMSizeATmega328); diff --git a/Functions.ino b/Functions.ino index 86739ee..450d3b4 100644 --- a/Functions.ino +++ b/Functions.ino @@ -6,7 +6,10 @@ void weldControlNoTFT() void weldControlTFT() { //if(continuously && BCDswitch()==0) weld(weldButton.on()); - if(continuously) weld(weldButton.on()); + if(continuously) + { + weld(weldButton.on()); + } else if(weldButton.pushed()) weldCyclus(menuItems[2].upDownVal); } @@ -38,8 +41,19 @@ void pulseWeld(int ms) } void weld(bool b) -{ digitalWrite(weldPin, b); +{ + if (b) + menu.displayDot(1); // Indicates thyristors are on + else + menu.displayDot(0); // Indicates thyristors are off + + if (b && !PrevWeld && !sinMaxDisabled) // If it is the first weld button press, + sinusMax(); // waits for voltage sinus max + + digitalWrite(weldPin, b); digitalWrite(ledPin, !b); + + PrevWeld = b; } void sinusMax() @@ -97,10 +111,11 @@ void TFTinit() tft.setOrientation(eeprom.readInt(orientation)); tft.setFont(Terminal12x16); } - + +// Detects if old (no LCD) or new (with LCD) PCB is being used bool TFTusedJumper() -{ pinMode(tftJumperOutPin, OUTPUT); - pinMode(tftJumperInPin, INPUT_PULLUP); // default 1 +{ pinMode(tftJumperOutPin, OUTPUT); // Defines this pin as bein an output + pinMode(tftJumperInPin, INPUT_PULLUP); // Defines this pin as being an input with a pull-up resistor digitalWrite(tftJumperOutPin, 0); return !digitalRead(tftJumperInPin); // no jumper = 1 (compatible with old software) } @@ -109,7 +124,8 @@ void printValuesToSerial() { Serial << "\npreweld " << menuItems[0].upDownVal << "ms, pause " << menuItems[1].upDownVal << "ms, weldTime " << menuItems[2].upDownVal << "ms, continuously " << continuously << endl; } - + +// LCD Orientation can only be either 0 or 2 void setOrientation() { pollAll(); // works without too if(upButton.on() && downButton.on()) diff --git a/README.md b/README.md index 1318425..611b070 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,9 @@ Arduino spot welder controller / solid state relay See the article: http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html + +version 6.2 compiled with the Arduino IDE 1.8.1 should give this output: +------------------------------------------------------------------------- +Sketch uses 14470 bytes (44%) of program storage space. Maximum is 32256 bytes. +Global variables use 792 bytes (38%) of dynamic memory, leaving 1256 bytes for local variables. Maximum is 2048 bytes. +------------------------------------------------------------------------- diff --git a/Spotwelder-6.2.ino b/Spotwelder-6.2.ino new file mode 100644 index 0000000..153f6bb --- /dev/null +++ b/Spotwelder-6.2.ino @@ -0,0 +1,90 @@ + +// Warning, set sinMaxDisabled = 0 for the production firmware +bool sinMaxDisabled = 0; // Use this for the final product +// bool sinMaxDisabled = 1; // Use this for testing without transformer + +/* +Note: use the latest Arduino software and install the libraries. + +Arduino spot welder controller +http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html + +Copyright (C) 2012 Albert van Dalen +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . +Version 5.2 1-02-2015 +Version 6.0 2-01-2017 added menu with TFT display +Version 6.1 22-05-2017 added set display orientation + +Program with FTDI programmer, Extra > Board > Arduino Uno + + < 20ms >< >sinusMax_us + _____ _____ _____ +zeroCross __| |_____| |_____| |__ + _____________ +weld __________________| |____ +T = 1/50Hz = 20ms +T/4 = 5 ms, 5e-3*16e6Hz = 80000 cc + +T = 1/60Hz = 16.667ms +T/4 = 4.1667 ms, 4.1667e-3*16e6Hz = 66666.67 cc +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "Definitions.h" +#include "Classes.h" +#include "Eeprom.h" + +Switch weldButton(weldButtonPin); +Switch upButton(upButtonPin); +Switch downButton(downButtonPin); +Switch selectButton(selectButtonPin); +TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // hardware SPI +// Defines the main menu entry names/items +MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue +MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(100, 50, 0, 1000)); +MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 50, 1000)); +MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; +UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 +Menu menu; +Eeprom eeprom; + +bool TFTused; +bool continuously; +bool PrevWeld; +unsigned orientation; + +void setup() +{ Serial.begin(9600); + eeprom.init(); + eeprom.read(); + setpinModes(); + TFTused = TFTusedJumper(); + // eeprom.writeInt(orientation, 2); // <------------------------------- + setOrientation(); // after eeprom.init() + if(TFTused) TFTinit(); + if(!TFTused) blinkLed(4); // This code can be removed if new PCB is used + digitalWrite(ledPin, 1); // power on indication + selectContinuously(); + printValuesToSerial(); + if(TFTused) menu.displayAll(); +} + +void loop() +{ pollAll(); + if(TFTused) + { menu.control(); + weldControlTFT(); + } else + weldControlNoTFT(); +} + + From 8cdf3a8e9d91687bd102dd7031b7ffdd24028bd6 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 08:29:02 +0200 Subject: [PATCH 02/19] Update Spotwelder-6.2.ino --- Spotwelder-6.2.ino | 171 ++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 86 deletions(-) diff --git a/Spotwelder-6.2.ino b/Spotwelder-6.2.ino index 153f6bb..1aa94be 100644 --- a/Spotwelder-6.2.ino +++ b/Spotwelder-6.2.ino @@ -1,90 +1,89 @@ - // Warning, set sinMaxDisabled = 0 for the production firmware -bool sinMaxDisabled = 0; // Use this for the final product -// bool sinMaxDisabled = 1; // Use this for testing without transformer - -/* -Note: use the latest Arduino software and install the libraries. - -Arduino spot welder controller -http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html - -Copyright (C) 2012 Albert van Dalen -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . -Version 5.2 1-02-2015 -Version 6.0 2-01-2017 added menu with TFT display -Version 6.1 22-05-2017 added set display orientation - -Program with FTDI programmer, Extra > Board > Arduino Uno - - < 20ms >< >sinusMax_us - _____ _____ _____ -zeroCross __| |_____| |_____| |__ - _____________ -weld __________________| |____ -T = 1/50Hz = 20ms -T/4 = 5 ms, 5e-3*16e6Hz = 80000 cc - -T = 1/60Hz = 16.667ms -T/4 = 4.1667 ms, 4.1667e-3*16e6Hz = 66666.67 cc -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "Definitions.h" -#include "Classes.h" -#include "Eeprom.h" - -Switch weldButton(weldButtonPin); -Switch upButton(upButtonPin); -Switch downButton(downButtonPin); -Switch selectButton(selectButtonPin); -TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // hardware SPI +//bool sinMaxDisabled = 0; +bool sinMaxDisabled = 1; // Set this for testing without transformer + +/* +Note: use the latest Arduino software and install the libraries. + +Arduino spot welder controller +http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html + +Copyright (C) 2012 Albert van Dalen +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . +Version 5.2 1-02-2015 +Version 6.0 2-01-2017 added menu with TFT display +Version 6.1 22-05-2017 added set display orientation + +Program with FTDI programmer, Extra > Board > Arduino Uno + + < 20ms >< >sinusMax_us + _____ _____ _____ +zeroCross __| |_____| |_____| |__ + _____________ +weld __________________| |____ + +T = 1/(4*50Hz) = 5000us +T = 1/(4*60Hz) = 4167us +Average time = (5000us + 4167us)/2 = 4583us +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "Definitions.h" +#include "Classes.h" +#include "Eeprom.h" + +Switch weldButton(weldButtonPin); +Switch upButton(upButtonPin); +Switch downButton(downButtonPin); +Switch selectButton(selectButtonPin); +TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // hardware SPI // Defines the main menu entry names/items -MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue -MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(100, 50, 0, 1000)); -MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 50, 1000)); -MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; -UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 -Menu menu; -Eeprom eeprom; - -bool TFTused; -bool continuously; +MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue +MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(500, 50, 0, 1000)); +MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 50, 1000)); +MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; +UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 +Menu menu; +Eeprom eeprom; + +bool TFTused; +bool continuously; bool PrevWeld; -unsigned orientation; - -void setup() -{ Serial.begin(9600); - eeprom.init(); - eeprom.read(); - setpinModes(); - TFTused = TFTusedJumper(); - // eeprom.writeInt(orientation, 2); // <------------------------------- - setOrientation(); // after eeprom.init() - if(TFTused) TFTinit(); - if(!TFTused) blinkLed(4); // This code can be removed if new PCB is used - digitalWrite(ledPin, 1); // power on indication - selectContinuously(); - printValuesToSerial(); - if(TFTused) menu.displayAll(); -} - -void loop() -{ pollAll(); - if(TFTused) - { menu.control(); - weldControlTFT(); - } else - weldControlNoTFT(); -} - +unsigned orientation; + +void setup() +{ Serial.begin(9600); + eeprom.init(); + eeprom.read(); + setpinModes(); + // eeprom.writeInt(orientation, 2); / for new PCB with TFT + + // For old PCB with or without TFT: + TFTused = TFTusedJumper(); + setOrientation(); // do after eeprom.init() + if(TFTused) TFTinit(); + if(!TFTused) blinkLed(4); + digitalWrite(ledPin, 1); // power on indication + selectContinuously(); + printValuesToSerial(); + if(TFTused) menu.displayAll(); +} + +void loop() +{ pollAll(); + if(TFTused) + { menu.control(); + weldControlTFT(); + } else + weldControlNoTFT(); +} From 7df48ee9a0c2ce445edac9f999db736133fc5216 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 08:32:44 +0200 Subject: [PATCH 03/19] Update Classes.ino --- Classes.ino | 206 ++++++++++++++++++++++++++-------------------------- 1 file changed, 102 insertions(+), 104 deletions(-) diff --git a/Classes.ino b/Classes.ino index b2d2eb2..adb2561 100644 --- a/Classes.ino +++ b/Classes.ino @@ -1,109 +1,107 @@ -#include "Classes.h" -#include - -void Menu::drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor) -{ tft.fillRectangle(left, 20*line, 175, 20*line+19, backgroundColor); // line <= 10 - tft.setBackgroundColor(backgroundColor); - tft.drawText(left, 20*line+2, str, color); -} - -void Menu::control() -{ if(!editValue) - { if(upButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item - menu.displayValue(upDownItemNr, menuItems[upDownItemNr.down()].upDownVal, 1, editValue); // focus - return; - } - if(downButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item - menu.displayValue(upDownItemNr, menuItems[upDownItemNr.up()].upDownVal, 1, editValue); // focus - return; - } - if(selectButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=1); // add backgound - return; - } - } - if(editValue) - { if(upButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.up(), 1, editValue); - return; - } - if(downButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.down(), 1, editValue); - return; - } - if(selectButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=0); // delete backgound - eeprom.write(); - return; - } - } -} - -void Menu::displayAll() -{ if(!continuously) - { for(int i=0; i<3; i++) - { upDownItemNr.value=i; - displayName(upDownItemNr, menuItems[upDownItemNr].name); - menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, 0); - } - upDownItemNr.value = 0; - menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, 0); // item 0 has focus - displayDot(0); - drawColorTextLine(10, 0, "- + sel weld", COLOR_YELLOW, COLOR_BLUEVIOLET); +#include "Classes.h" +#include + +void Menu::drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor) +{ tft.fillRectangle(left, 20*line, 175, 20*line+19, backgroundColor); // line <= 10 + tft.setBackgroundColor(backgroundColor); + tft.drawText(left, 20*line+2, str, color); +} + +void Menu::control() +{ if(!editValue) + { if(upButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item + menu.displayValue(upDownItemNr, menuItems[upDownItemNr.down()].upDownVal, 1, editValue); // focus + return; + } + if(downButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item + menu.displayValue(upDownItemNr, menuItems[upDownItemNr.up()].upDownVal, 1, editValue); // focus + return; + } + if(selectButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=1); // add backgound + return; + } + } + if(editValue) + { if(upButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.up(), 1, editValue); + return; + } + if(downButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.down(), 1, editValue); + return; + } + if(selectButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=0); // delete backgound + eeprom.write(); + return; + } + } +} + +void Menu::displayAll() +{ if(!continuously) + { for(int i=0; i<3; i++) + { upDownItemNr.value=i; + displayName(upDownItemNr, menuItems[upDownItemNr].name); + menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, 0); + } + upDownItemNr.value = 0; + menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, 0); // item 0 has focus + displayDot(0); + drawColorTextLine(10, 0, "- + sel weld", COLOR_YELLOW, COLOR_BLUEVIOLET); // drawColorTextLine(10, 0, "Weld Sel Up Down", COLOR_YELLOW, COLOR_BLUEVIOLET); - } - else - { drawColorTextLine(4, 0, " Continuously", COLOR_WHITE, COLOR_RED); - drawColorTextLine(5, 0, " mode", COLOR_WHITE, COLOR_RED); - drawColorTextLine(6, 0, " Take care!", COLOR_WHITE, COLOR_RED); + } + else + { drawColorTextLine(4, 0, " Continuously", COLOR_WHITE, COLOR_RED); + drawColorTextLine(5, 0, " mode", COLOR_WHITE, COLOR_RED); + drawColorTextLine(6, 0, " Take care!", COLOR_WHITE, COLOR_RED); // drawColorTextLine(10, 0, "Weld ", COLOR_YELLOW, COLOR_BLUEVIOLET); drawColorTextLine(10, 0, " Weld", COLOR_YELLOW, COLOR_BLUEVIOLET); - } -} - -void Menu::displayDot(bool on) -// { tft.fillCircle(87, 170, 12, on? COLOR_WHITE : COLOR_DARKBLUE); -{ tft.fillCircle(87, 170, 12, on? COLOR_RED : COLOR_DARKGREEN); -} - -void Menu::displayName(int upDownItemNr, String &name) -{ drawColorTextLine(2*upDownItemNr, txtLeft, name, TXT_COLOR); -} - -void Menu::displayValue(int upDownItemNr, int value, bool focus, bool background) -{ menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(" ")); // clear line - menu.drawColorTextLine(2*upDownItemNr+1, 0, focus? ">" : " ", TXT_COLOR1); - menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(value), background? COLOR_BLACK : TXT_COLOR1, background? COLOR_CYAN : COLOR_BLACK); -} - -// --------------------------------------------------------------------------- - -UpDownValue::UpDownValue(int value, int step, int minValue, int maxValue): -value(value), step(step), minValue(minValue), maxValue(maxValue) -{ -} -int UpDownValue::up() -{ value += step; - // return value = min(max(value, minValue), maxValue); - return value = (value > maxValue) ? minValue : value; -} -int UpDownValue::down() -{ value -= step; - // return value = min(max(value, minValue), maxValue); + } +} + +void Menu::displayDot(bool on) +{ tft.fillCircle(87, 170, 12, on? COLOR_RED : COLOR_DARKGREEN); +} + +void Menu::displayName(int upDownItemNr, String &name) +{ drawColorTextLine(2*upDownItemNr, txtLeft, name, TXT_COLOR); +} + +void Menu::displayValue(int upDownItemNr, int value, bool focus, bool background) +{ menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(" ")); // clear line + menu.drawColorTextLine(2*upDownItemNr+1, 0, focus? ">" : " ", TXT_COLOR1); + menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(value), background? COLOR_BLACK : TXT_COLOR1, background? COLOR_CYAN : COLOR_BLACK); +} + +// --------------------------------------------------------------------------- + +UpDownValue::UpDownValue(int value, int step, int minValue, int maxValue): +value(value), step(step), minValue(minValue), maxValue(maxValue) +{ +} +int UpDownValue::up() +{ value += step; + // return value = min(max(value, minValue), maxValue); // stops at end + return value = (value > maxValue) ? minValue : value; +} +int UpDownValue::down() +{ value -= step; + // return value = min(max(value, minValue), maxValue); // stops at end return value = (value < minValue ) ? maxValue : value; -} - -UpDownValue::operator int() // conversion operator, object returns value -{ return value; -} - -// --------------------------------------------------------------------------- - -MenuItem::MenuItem(String name, UpDownValue value): -name(name), upDownVal(value) -{ -} - +} + +UpDownValue::operator int() // conversion operator, object returns value +{ return value; +} + +// --------------------------------------------------------------------------- + +MenuItem::MenuItem(String name, UpDownValue value): +name(name), upDownVal(value) +{ +} From 2160ef9623129734a14df62cd536bfcd8670777b Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 08:33:55 +0200 Subject: [PATCH 04/19] Update Functions.ino --- Functions.ino | 247 ++++++++++++++++++++++++-------------------------- 1 file changed, 116 insertions(+), 131 deletions(-) diff --git a/Functions.ino b/Functions.ino index 450d3b4..a0475cb 100644 --- a/Functions.ino +++ b/Functions.ino @@ -1,137 +1,122 @@ -void weldControlNoTFT() -{ if(continuously && BCDswitch()==0) weld(weldButton.on()); // continuous welding - else - if(weldButton.pushed()) weldCyclus(BCDswitch() * step_ms); -} - -void weldControlTFT() -{ //if(continuously && BCDswitch()==0) weld(weldButton.on()); - if(continuously) - { - weld(weldButton.on()); - } - else - if(weldButton.pushed()) weldCyclus(menuItems[2].upDownVal); -} - -void weldCyclus(int weldTime_ms) -{ if(!sinMaxDisabled) sinusMax(); - if(TFTused) menu.displayDot(1); // just once per weld cyclus - pulseWeld(menuItems[0].upDownVal); - delay(menuItems[1].upDownVal); - if(!sinMaxDisabled) sinusMax(); - pulseWeld(weldTime_ms); - if(TFTused) menu.displayDot(0); // just once per weld cyclus -} - -int BCDswitch() -{ int bcd; - bitWrite(bcd, 0, !digitalRead(BCDswitch0pin)); - bitWrite(bcd, 1, !digitalRead(BCDswitch1pin)); - bitWrite(bcd, 2, !digitalRead(BCDswitch2pin)); - bitWrite(bcd, 3, !digitalRead(BCDswitch3pin)); - return bcd; -} - -void pulseWeld(int ms) -{ weld(1); - delay(ms); - weld(0); - if(printValuesToSerial) Serial << ms << endl; -} - -void weld(bool b) -{ - if (b) - menu.displayDot(1); // Indicates thyristors are on +void weldControlNoTFT() +{ if(continuously && BCDswitch()==0) weld(weldButton.on()); // continuous welding else - menu.displayDot(0); // Indicates thyristors are off - - if (b && !PrevWeld && !sinMaxDisabled) // If it is the first weld button press, - sinusMax(); // waits for voltage sinus max - - digitalWrite(weldPin, b); - digitalWrite(ledPin, !b); + if(weldButton.pushed()) weldCyclus(BCDswitch() * step_ms); +} + +void weldControlTFT() +{ if(continuously) weld(weldButton.on()); + else + if(weldButton.pushed()) weldCyclus(menuItems[2].upDownVal); +} +void weldCyclus(int weldTime_ms) +{ if(!sinMaxDisabled) sinusMax(); + pulseWeld(menuItems[0].upDownVal); + delay(menuItems[1].upDownVal); + if(!sinMaxDisabled) sinusMax(); + pulseWeld(weldTime_ms); +} + +int BCDswitch() +{ int bcd; + bitWrite(bcd, 0, !digitalRead(BCDswitch0pin)); + bitWrite(bcd, 1, !digitalRead(BCDswitch1pin)); + bitWrite(bcd, 2, !digitalRead(BCDswitch2pin)); + bitWrite(bcd, 3, !digitalRead(BCDswitch3pin)); + return bcd; +} + +void pulseWeld(int ms) +{ weld(1); + delay(ms); + weld(0); + if(printValuesToSerial) Serial << ms << endl; +} + +void weld(bool b) +{ if(b) menu.displayDot(1); // Indicates thyristors are on + else menu.displayDot(0); // Indicates thyristors are off + if (b && !PrevWeld && !sinMaxDisabled) sinusMax(); // If first weld button press, wait on sinus max + digitalWrite(weldPin, b); + digitalWrite(ledPin, !b); PrevWeld = b; -} - -void sinusMax() -{ while(digitalRead(zeroCrossPin)); - while(!digitalRead(zeroCrossPin)); - delayMicroseconds(sinusMax_us); // to prevent inrush current, turn-on at the sinus max -} - -void blinkLed(int n) -{ pinMode(ledPin, OUTPUT); - for(byte i=0; i weldButtonPressTime) continuously = 1; - if(!TFTused) continuously &= bcdswitch==0; // bcdswitch has to be at position 0 too -} - -void TFTinit() -{ tft.begin(); - tft.setOrientation(eeprom.readInt(orientation)); - tft.setFont(Terminal12x16); -} +} + +void sinusMax() +{ while(digitalRead(zeroCrossPin)); + while(!digitalRead(zeroCrossPin)); + delayMicroseconds(sinusMax_us); // to prevent inrush current, turn-on at the sinus max +} + +void blinkLed(int n) +{ pinMode(ledPin, OUTPUT); + for(byte i=0; i weldButtonPressTime) continuously = 1; + if(!TFTused) continuously &= bcdswitch==0; // bcdswitch has to be at position 0 too +} + +void TFTinit() +{ tft.begin(); + tft.setOrientation(eeprom.readInt(orientation)); + tft.setFont(Terminal12x16); +} + +// Detects if a PCB with or without LCD is being used +bool TFTusedJumper() +{ pinMode(tftJumperOutPin, OUTPUT); // Defines this pin as being an output + pinMode(tftJumperInPin, INPUT_PULLUP); // Defines this pin as being an input with a pull-up resistor + digitalWrite(tftJumperOutPin, 0); + return !digitalRead(tftJumperInPin); // no jumper = 1 (compatible with old software) +} -// Detects if old (no LCD) or new (with LCD) PCB is being used -bool TFTusedJumper() -{ pinMode(tftJumperOutPin, OUTPUT); // Defines this pin as bein an output - pinMode(tftJumperInPin, INPUT_PULLUP); // Defines this pin as being an input with a pull-up resistor - digitalWrite(tftJumperOutPin, 0); - return !digitalRead(tftJumperInPin); // no jumper = 1 (compatible with old software) -} - -void printValuesToSerial() -{ Serial << "\npreweld " << menuItems[0].upDownVal << "ms, pause " << menuItems[1].upDownVal << "ms, weldTime " - << menuItems[2].upDownVal << "ms, continuously " << continuously << endl; -} +void printValuesToSerial() +{ Serial << "\npreweld " << menuItems[0].upDownVal << "ms, pause " << menuItems[1].upDownVal << "ms, weldTime " + << menuItems[2].upDownVal << "ms, continuously " << continuously << endl; +} -// LCD Orientation can only be either 0 or 2 -void setOrientation() -{ pollAll(); // works without too - if(upButton.on() && downButton.on()) - { if(eeprom.readInt(orientation)==0) eeprom.writeInt(orientation, 2); - else eeprom.writeInt(orientation, 0); - } -} - +void setOrientation() +{ pollAll(); // works without too + if(upButton.on() && downButton.on()) + { if(eeprom.readInt(orientation)==0) eeprom.writeInt(orientation, 2); // LCD Orientation can only be either 0 or 2 + else eeprom.writeInt(orientation, 0); + } +} From 033b79545b25407226ae51d69e14122050e3a14c Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 08:34:49 +0200 Subject: [PATCH 05/19] Update Definitions.h --- Definitions.h | 57 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/Definitions.h b/Definitions.h index 32522ba..5f419de 100644 --- a/Definitions.h +++ b/Definitions.h @@ -1,31 +1,30 @@ -#ifndef _Definitions_H_ -#define _Definitions_H_ - -const byte BCDswitch0pin = 8; -const byte BCDswitch1pin = 7; -const byte BCDswitch2pin = 6; -const byte BCDswitch3pin = 5; -const byte weldPin = 2; -const byte weldButtonPin = 4; -const byte upButtonPin = 7; -const byte downButtonPin = 8; -const byte selectButtonPin = 6; -const byte ledPin = 12; -const byte zeroCrossPin = 3; -const byte tftJumperOutPin = A5; -const byte tftJumperInPin = A4; - -const byte TFT_RSTpin = 9; -const byte TFT_RSpin = 10; -const byte TFT_CSpin = 5; -//const byte TFT_CLKpin = 13; // for SW SDI, doesn't work -//const byte TFT_SDIpin = 11; // for SW SDI, doesn't work - -const int step_ms = 50; -// const int sinusMax_us = 4583; -const int sinusMax_us = 5000; - -#define TXT_COLOR COLOR_YELLOW +#ifndef _Definitions_H_ +#define _Definitions_H_ + +const byte BCDswitch0pin = 8; +const byte BCDswitch1pin = 7; +const byte BCDswitch2pin = 6; +const byte BCDswitch3pin = 5; +const byte weldPin = 2; +const byte weldButtonPin = 4; +const byte upButtonPin = 7; +const byte downButtonPin = 8; +const byte selectButtonPin = 6; +const byte ledPin = 12; +const byte zeroCrossPin = 3; +const byte tftJumperOutPin = A5; +const byte tftJumperInPin = A4; + +const byte TFT_RSTpin = 9; +const byte TFT_RSpin = 10; +const byte TFT_CSpin = 5; +//const byte TFT_CLKpin = 13; // for SW SDI, doesn't work +//const byte TFT_SDIpin = 11; // for SW SDI, doesn't work + +const int step_ms = 50; +const int sinusMax_us = 4583; // for 50Hz and 60Hz + +#define TXT_COLOR COLOR_YELLOW #define TXT_COLOR1 COLOR_SNOW - + #endif From 3f2d6b912124058f2a3ce958c3b5aa1b4cca3426 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 08:35:42 +0200 Subject: [PATCH 06/19] Update Eeprom.ino --- Eeprom.ino | 62 ++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/Eeprom.ino b/Eeprom.ino index 31d0541..824bf5e 100644 --- a/Eeprom.ino +++ b/Eeprom.ino @@ -1,33 +1,31 @@ -const unsigned maxWrites = 100; -// const unsigned initValue = 123456; // take another value for new initialization -const uint16_t initValue = 12345; // take another value for new initialization - -void Eeprom::init() -{ setMemPool(0, EEPROMSizeATmega328); - setMaxAllowedWrites(maxWrites); - storedInitValue = getAddress(sizeof(unsigned)); - preweld_ms = getAddress(sizeof(unsigned)); - pause_ms = getAddress(sizeof(unsigned)); - weld_ms = getAddress(sizeof(unsigned)); - orientation = getAddress(sizeof(unsigned)); - if(!initialized()) write(); // fill an empty EEPROM -} - -void Eeprom::read() -{ menuItems[0].upDownVal.value = readInt(preweld_ms); - menuItems[1].upDownVal.value = readInt(pause_ms); - menuItems[2].upDownVal.value = readInt(weld_ms); -} - -void Eeprom::write() -{ writeInt(storedInitValue, initValue); // todo with update()? - writeInt(preweld_ms, menuItems[0].upDownVal.value); - writeInt(pause_ms, menuItems[1].upDownVal.value); - writeInt(weld_ms, menuItems[2].upDownVal.value); - writeInt(orientation, 0); -} - -bool Eeprom::initialized() -{ return readInt(storedInitValue) == initValue; -} +const unsigned maxWrites = 100; +const unsigned initValue = 123455; // take another value for new initialization +void Eeprom::init() +{ setMemPool(0, EEPROMSizeATmega328); + setMaxAllowedWrites(maxWrites); + storedInitValue = getAddress(sizeof(unsigned)); + preweld_ms = getAddress(sizeof(unsigned)); + pause_ms = getAddress(sizeof(unsigned)); + weld_ms = getAddress(sizeof(unsigned)); + orientation = getAddress(sizeof(unsigned)); + if(!initialized()) write(); // fill an empty EEPROM +} + +void Eeprom::read() +{ menuItems[0].upDownVal.value = readInt(preweld_ms); + menuItems[1].upDownVal.value = readInt(pause_ms); + menuItems[2].upDownVal.value = readInt(weld_ms); +} + +void Eeprom::write() +{ writeInt(storedInitValue, initValue); // todo with update()? + writeInt(preweld_ms, menuItems[0].upDownVal.value); + writeInt(pause_ms, menuItems[1].upDownVal.value); + writeInt(weld_ms, menuItems[2].upDownVal.value); + writeInt(orientation, 0); +} + +bool Eeprom::initialized() +{ return readInt(storedInitValue) == initValue; +} From aa5e283850c845cbb02254641ca92bcf16ddedbc Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 08:42:07 +0200 Subject: [PATCH 07/19] Delete Spotwelder-6.1.ino --- Spotwelder-6.1.ino | 79 ---------------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 Spotwelder-6.1.ino diff --git a/Spotwelder-6.1.ino b/Spotwelder-6.1.ino deleted file mode 100644 index c735b30..0000000 --- a/Spotwelder-6.1.ino +++ /dev/null @@ -1,79 +0,0 @@ -bool sinMaxDisabled = 0; // for test without transformer, must be 0 - -/* -Note: use the latest Arduino software and install the libraries. - -Arduino spot welder controller -http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html - -Copyright (C) 2012 Albert van Dalen -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . -Version 5.2 1-02-2015 -Version 6.0 2-01-2017 added menu with TFT display -Version 6.1 22-05-2017 added set display orientation - -Program with FTDI programmer, Extra > Board > Arduino Uno - - < 20ms >< >sinusMax_us - _____ _____ _____ -zeroCross __| |_____| |_____| |__ - _____________ -weld __________________| |____ -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "Definitions.h" -#include "Classes.h" -#include "Eeprom.h" - -Switch weldButton(weldButtonPin); -Switch upButton(upButtonPin); -Switch downButton(downButtonPin); -Switch selectButton(selectButtonPin); -TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // hardware SPI -MenuItem preweldTimeItem = MenuItem("Preweld time", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue -MenuItem pauseTimeItem = MenuItem("Pause", UpDownValue(500, 100, 0, 1000)); -MenuItem weldTimeItem = MenuItem("Weld time", UpDownValue(250, 50, 50, 1000)); -MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; -UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 -Menu menu; -Eeprom eeprom; - -bool TFTused; -bool continuously; -unsigned orientation; - -void setup() -{ Serial.begin(9600); - eeprom.init(); - eeprom.read(); - setpinModes(); - TFTused = TFTusedJumper(); - setOrientation(); // after eeprom.init() - if(TFTused) TFTinit(); - if(!TFTused) blinkLed(4); - digitalWrite(ledPin, 1); // power on indication - selectContinuously(); - printValuesToSerial(); - if(TFTused) menu.displayAll(); -} - -void loop() -{ pollAll(); - if(TFTused) - { menu.control(); - weldControlTFT(); - } else - weldControlNoTFT(); -} - - From ddc473d32a77f74e7b59c4fc6375d6e7cb07da4d Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 16:31:11 +0200 Subject: [PATCH 08/19] Update Spotwelder-6.2.ino --- Spotwelder-6.2.ino | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Spotwelder-6.2.ino b/Spotwelder-6.2.ino index 1aa94be..fcf853b 100644 --- a/Spotwelder-6.2.ino +++ b/Spotwelder-6.2.ino @@ -1,6 +1,5 @@ // Warning, set sinMaxDisabled = 0 for the production firmware -//bool sinMaxDisabled = 0; -bool sinMaxDisabled = 1; // Set this for testing without transformer +bool sinMaxDisabled = 0; // Set this 0 for testing without transformer /* Note: use the latest Arduino software and install the libraries. @@ -27,7 +26,7 @@ weld __________________| |____ T = 1/(4*50Hz) = 5000us T = 1/(4*60Hz) = 4167us -Average time = (5000us + 4167us)/2 = 4583us +Average time sinusMax_us = (5000us + 4167us)/2 = 4583us, this does not have to be exact */ #include @@ -41,6 +40,8 @@ Average time = (5000us + 4167us)/2 = 4583us #include "Classes.h" #include "Eeprom.h" +String version = "Version 6.2"; + Switch weldButton(weldButtonPin); Switch upButton(upButtonPin); Switch downButton(downButtonPin); @@ -76,7 +77,11 @@ void setup() digitalWrite(ledPin, 1); // power on indication selectContinuously(); printValuesToSerial(); - if(TFTused) menu.displayAll(); + if(TFTused) + { menu.displayName(0, version); + delay(500); + menu.displayAll(); + } } void loop() From 5b859e206f6b738034cb6bea6a3b7ab348a03c3d Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 17:00:32 +0200 Subject: [PATCH 09/19] Update Spotwelder-6.2.ino --- Spotwelder-6.2.ino | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Spotwelder-6.2.ino b/Spotwelder-6.2.ino index fcf853b..a8dc378 100644 --- a/Spotwelder-6.2.ino +++ b/Spotwelder-6.2.ino @@ -1,5 +1,5 @@ // Warning, set sinMaxDisabled = 0 for the production firmware -bool sinMaxDisabled = 0; // Set this 0 for testing without transformer +bool sinMaxDisabled = 1; // Set this 0 for testing without transformer /* Note: use the latest Arduino software and install the libraries. @@ -50,7 +50,7 @@ TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // har // Defines the main menu entry names/items MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(500, 50, 0, 1000)); -MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 50, 1000)); +MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 0, 1000)); MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 Menu menu; @@ -58,7 +58,7 @@ Eeprom eeprom; bool TFTused; bool continuously; -bool PrevWeld; +//bool PrevWeld; unsigned orientation; void setup() @@ -77,11 +77,7 @@ void setup() digitalWrite(ledPin, 1); // power on indication selectContinuously(); printValuesToSerial(); - if(TFTused) - { menu.displayName(0, version); - delay(500); - menu.displayAll(); - } + if(TFTused) menu.displayAll(); } void loop() @@ -92,3 +88,4 @@ void loop() } else weldControlNoTFT(); } + From df160e56ce00f3fa5e4ca882248a03bbd9c7d0d2 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 17:02:42 +0200 Subject: [PATCH 10/19] Update Classes.h --- Classes.h | 82 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/Classes.h b/Classes.h index 9fe775b..c857702 100644 --- a/Classes.h +++ b/Classes.h @@ -1,42 +1,42 @@ -#ifndef _Classes_H_ -#define _Classes_H_ - -#include - -class UpDownValue -{ public: - UpDownValue(int value, int step, int minValue, int maxValue); - int up(); - int down(); - UpDownValue::operator int(); - - int value, step, minValue, maxValue; -}; - -// --------------------------------------------------------------------------- - -class MenuItem -{ public: - MenuItem(String name, UpDownValue value); - - String name; - UpDownValue upDownVal; -}; - -// --------------------------------------------------------------------------- - -class Menu -{ public: - void control(); - void displayAll(); - void displayName(int itemNr, String &name); - void displayValue(int itemNr, int value, bool focus, bool background); - void displayDot(bool on); - void drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor=COLOR_BLACK); - - private: - bool editValue=0; - const int txtLeft = 17; -}; - +#ifndef _Classes_H_ +#define _Classes_H_ + +#include + +class UpDownValue +{ public: + UpDownValue(int value, int step, int minValue, int maxValue); + int up(); + int down(); + UpDownValue::operator int(); + + int value, step, minValue, maxValue; +}; + +// --------------------------------------------------------------------------- + +class MenuItem +{ public: + MenuItem(String name, UpDownValue value); + + String name; + UpDownValue upDownVal; +}; + +// --------------------------------------------------------------------------- + +class Menu +{ public: + void control(); + void displayAll(); + void displayName(int itemNr, String &name); + void displayValue(int itemNr, int value, bool focus, bool background); + void displayDot(bool on); + void drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor=COLOR_BLACK); + + private: + bool editValue=0; + const int txtLeft = 17; +}; + #endif From 9690b7b211e81eb7357b22704024fc889008def4 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 17:03:29 +0200 Subject: [PATCH 11/19] Update Classes.ino --- Classes.ino | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Classes.ino b/Classes.ino index adb2561..ac74b0b 100644 --- a/Classes.ino +++ b/Classes.ino @@ -42,7 +42,10 @@ void Menu::control() } void Menu::displayAll() -{ if(!continuously) +{ displayName(0, version); + delay(500); + + if(!continuously) { for(int i=0; i<3; i++) { upDownItemNr.value=i; displayName(upDownItemNr, menuItems[upDownItemNr].name); @@ -62,7 +65,7 @@ void Menu::displayAll() drawColorTextLine(10, 0, " Weld", COLOR_YELLOW, COLOR_BLUEVIOLET); } } - + void Menu::displayDot(bool on) { tft.fillCircle(87, 170, 12, on? COLOR_RED : COLOR_DARKGREEN); } @@ -83,11 +86,13 @@ UpDownValue::UpDownValue(int value, int step, int minValue, int maxValue): value(value), step(step), minValue(minValue), maxValue(maxValue) { } + int UpDownValue::up() { value += step; // return value = min(max(value, minValue), maxValue); // stops at end return value = (value > maxValue) ? minValue : value; } + int UpDownValue::down() { value -= step; // return value = min(max(value, minValue), maxValue); // stops at end From 04acab22df2ba6eae29d1e7d9048c8374fd0068a Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Thu, 24 Aug 2017 17:04:07 +0200 Subject: [PATCH 12/19] Update Functions.ino --- Functions.ino | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Functions.ino b/Functions.ino index a0475cb..9013aa8 100644 --- a/Functions.ino +++ b/Functions.ino @@ -35,12 +35,11 @@ void pulseWeld(int ms) } void weld(bool b) -{ if(b) menu.displayDot(1); // Indicates thyristors are on - else menu.displayDot(0); // Indicates thyristors are off - if (b && !PrevWeld && !sinMaxDisabled) sinusMax(); // If first weld button press, wait on sinus max +{ menu.displayDot(b); + // if (b && !PrevWeld && !sinMaxDisabled) sinusMax(); // If first weld button press, wait on sinus max digitalWrite(weldPin, b); digitalWrite(ledPin, !b); - PrevWeld = b; + //PrevWeld = b; } void sinusMax() From b62f341923621ddf3f3a66f05aa411e7ac552f47 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Sun, 27 Aug 2017 09:44:28 +0200 Subject: [PATCH 13/19] Add files via upload --- Classes.h | 82 ++++++++--------- Classes.ino | 219 ++++++++++++++++++++++----------------------- Definitions.h | 49 +++++----- Eeprom.ino | 61 ++++++------- Functions.ino | 204 +++++++++++++++++------------------------ README.md | 6 -- Spotwelder-SMD.ino | 81 +++++++++++++++++ 7 files changed, 365 insertions(+), 337 deletions(-) create mode 100644 Spotwelder-SMD.ino diff --git a/Classes.h b/Classes.h index c857702..9fe775b 100644 --- a/Classes.h +++ b/Classes.h @@ -1,42 +1,42 @@ -#ifndef _Classes_H_ -#define _Classes_H_ - -#include - -class UpDownValue -{ public: - UpDownValue(int value, int step, int minValue, int maxValue); - int up(); - int down(); - UpDownValue::operator int(); - - int value, step, minValue, maxValue; -}; - -// --------------------------------------------------------------------------- - -class MenuItem -{ public: - MenuItem(String name, UpDownValue value); - - String name; - UpDownValue upDownVal; -}; - -// --------------------------------------------------------------------------- - -class Menu -{ public: - void control(); - void displayAll(); - void displayName(int itemNr, String &name); - void displayValue(int itemNr, int value, bool focus, bool background); - void displayDot(bool on); - void drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor=COLOR_BLACK); - - private: - bool editValue=0; - const int txtLeft = 17; -}; - +#ifndef _Classes_H_ +#define _Classes_H_ + +#include + +class UpDownValue +{ public: + UpDownValue(int value, int step, int minValue, int maxValue); + int up(); + int down(); + UpDownValue::operator int(); + + int value, step, minValue, maxValue; +}; + +// --------------------------------------------------------------------------- + +class MenuItem +{ public: + MenuItem(String name, UpDownValue value); + + String name; + UpDownValue upDownVal; +}; + +// --------------------------------------------------------------------------- + +class Menu +{ public: + void control(); + void displayAll(); + void displayName(int itemNr, String &name); + void displayValue(int itemNr, int value, bool focus, bool background); + void displayDot(bool on); + void drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor=COLOR_BLACK); + + private: + bool editValue=0; + const int txtLeft = 17; +}; + #endif diff --git a/Classes.ino b/Classes.ino index ac74b0b..153485d 100644 --- a/Classes.ino +++ b/Classes.ino @@ -1,112 +1,109 @@ -#include "Classes.h" -#include - -void Menu::drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor) -{ tft.fillRectangle(left, 20*line, 175, 20*line+19, backgroundColor); // line <= 10 - tft.setBackgroundColor(backgroundColor); - tft.drawText(left, 20*line+2, str, color); -} - -void Menu::control() -{ if(!editValue) - { if(upButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item - menu.displayValue(upDownItemNr, menuItems[upDownItemNr.down()].upDownVal, 1, editValue); // focus - return; - } - if(downButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item - menu.displayValue(upDownItemNr, menuItems[upDownItemNr.up()].upDownVal, 1, editValue); // focus - return; - } - if(selectButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=1); // add backgound - return; - } - } - if(editValue) - { if(upButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.up(), 1, editValue); - return; - } - if(downButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.down(), 1, editValue); - return; - } - if(selectButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=0); // delete backgound - eeprom.write(); - return; - } - } -} - -void Menu::displayAll() -{ displayName(0, version); - delay(500); - - if(!continuously) - { for(int i=0; i<3; i++) - { upDownItemNr.value=i; - displayName(upDownItemNr, menuItems[upDownItemNr].name); - menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, 0); - } - upDownItemNr.value = 0; - menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, 0); // item 0 has focus - displayDot(0); - drawColorTextLine(10, 0, "- + sel weld", COLOR_YELLOW, COLOR_BLUEVIOLET); - // drawColorTextLine(10, 0, "Weld Sel Up Down", COLOR_YELLOW, COLOR_BLUEVIOLET); - } - else - { drawColorTextLine(4, 0, " Continuously", COLOR_WHITE, COLOR_RED); - drawColorTextLine(5, 0, " mode", COLOR_WHITE, COLOR_RED); - drawColorTextLine(6, 0, " Take care!", COLOR_WHITE, COLOR_RED); - // drawColorTextLine(10, 0, "Weld ", COLOR_YELLOW, COLOR_BLUEVIOLET); - drawColorTextLine(10, 0, " Weld", COLOR_YELLOW, COLOR_BLUEVIOLET); - } -} - -void Menu::displayDot(bool on) -{ tft.fillCircle(87, 170, 12, on? COLOR_RED : COLOR_DARKGREEN); -} - -void Menu::displayName(int upDownItemNr, String &name) -{ drawColorTextLine(2*upDownItemNr, txtLeft, name, TXT_COLOR); -} - -void Menu::displayValue(int upDownItemNr, int value, bool focus, bool background) -{ menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(" ")); // clear line - menu.drawColorTextLine(2*upDownItemNr+1, 0, focus? ">" : " ", TXT_COLOR1); - menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(value), background? COLOR_BLACK : TXT_COLOR1, background? COLOR_CYAN : COLOR_BLACK); -} - -// --------------------------------------------------------------------------- - -UpDownValue::UpDownValue(int value, int step, int minValue, int maxValue): -value(value), step(step), minValue(minValue), maxValue(maxValue) -{ -} - -int UpDownValue::up() -{ value += step; - // return value = min(max(value, minValue), maxValue); // stops at end - return value = (value > maxValue) ? minValue : value; -} - -int UpDownValue::down() -{ value -= step; - // return value = min(max(value, minValue), maxValue); // stops at end - return value = (value < minValue ) ? maxValue : value; -} - -UpDownValue::operator int() // conversion operator, object returns value -{ return value; -} - -// --------------------------------------------------------------------------- - -MenuItem::MenuItem(String name, UpDownValue value): -name(name), upDownVal(value) -{ -} +#include "Classes.h" +#include + +void Menu::drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor) +{ tft.fillRectangle(left, 20*line, 175, 20*line+19, backgroundColor); // line <= 10 + tft.setBackgroundColor(backgroundColor); + tft.drawText(left, 20*line+2, str, color); +} + +void Menu::control() +{ if(!editValue) + { if(upButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item + menu.displayValue(upDownItemNr, menuItems[upDownItemNr.down()].upDownVal, 1, editValue); // focus + return; + } + if(downButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item + menu.displayValue(upDownItemNr, menuItems[upDownItemNr.up()].upDownVal, 1, editValue); // focus + return; + } + if(selectButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=1); // add backgound + return; + } + } + if(editValue) + { if(upButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.up(), 1, editValue); + return; + } + if(downButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.down(), 1, editValue); + return; + } + if(selectButton.pushed()) + { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=0); // delete backgound + eeprom.write(); + return; + } + } +} + +void Menu::displayAll() +{ displayName(0, version); + delay(500); + + if(!continuously) + { for(int i=0; i<3; i++) + { upDownItemNr.value=i; + displayName(upDownItemNr, menuItems[upDownItemNr].name); + menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, 0); + } + upDownItemNr.value = 0; + menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, 0); // item 0 has focus + displayDot(0); + drawColorTextLine(10, 0, "- + sel weld", COLOR_YELLOW, COLOR_BLUEVIOLET); // todo no weld button text + } + else + { drawColorTextLine(4, 0, " Continuously", COLOR_WHITE, COLOR_RED); + drawColorTextLine(5, 0, " mode", COLOR_WHITE, COLOR_RED); + drawColorTextLine(6, 0, " Take care!", COLOR_WHITE, COLOR_RED); + drawColorTextLine(10, 0, " Weld", COLOR_YELLOW, COLOR_BLUEVIOLET); // todo no weld button text + } +} + +void Menu::displayDot(bool on) +{ tft.fillCircle(87, 170, 12, on? COLOR_RED : COLOR_DARKGREEN); +} + +void Menu::displayName(int upDownItemNr, String &name) +{ drawColorTextLine(2*upDownItemNr, txtLeft, name, TXT_COLOR); +} + +void Menu::displayValue(int upDownItemNr, int value, bool focus, bool background) +{ menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(" ")); // clear line + menu.drawColorTextLine(2*upDownItemNr+1, 0, focus? ">" : " ", TXT_COLOR1); + menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(value), background? COLOR_BLACK : TXT_COLOR1, background? COLOR_CYAN : COLOR_BLACK); +} + +// --------------------------------------------------------------------------- + +UpDownValue::UpDownValue(int value, int step, int minValue, int maxValue): +value(value), step(step), minValue(minValue), maxValue(maxValue) +{ +} + +int UpDownValue::up() +{ value += step; + return value = (value > maxValue) ? minValue : value; +} + +int UpDownValue::down() +{ value -= step; + return value = (value < minValue ) ? maxValue : value; +} + +UpDownValue::operator int() // conversion operator, object returns value +{ return value; +} + +// --------------------------------------------------------------------------- + +MenuItem::MenuItem(String name, UpDownValue value): +name(name), upDownVal(value) +{ +} + diff --git a/Definitions.h b/Definitions.h index 5f419de..c876ff8 100644 --- a/Definitions.h +++ b/Definitions.h @@ -1,30 +1,21 @@ -#ifndef _Definitions_H_ -#define _Definitions_H_ - -const byte BCDswitch0pin = 8; -const byte BCDswitch1pin = 7; -const byte BCDswitch2pin = 6; -const byte BCDswitch3pin = 5; -const byte weldPin = 2; -const byte weldButtonPin = 4; -const byte upButtonPin = 7; -const byte downButtonPin = 8; -const byte selectButtonPin = 6; -const byte ledPin = 12; -const byte zeroCrossPin = 3; -const byte tftJumperOutPin = A5; -const byte tftJumperInPin = A4; - -const byte TFT_RSTpin = 9; -const byte TFT_RSpin = 10; -const byte TFT_CSpin = 5; -//const byte TFT_CLKpin = 13; // for SW SDI, doesn't work -//const byte TFT_SDIpin = 11; // for SW SDI, doesn't work - -const int step_ms = 50; -const int sinusMax_us = 4583; // for 50Hz and 60Hz - -#define TXT_COLOR COLOR_YELLOW -#define TXT_COLOR1 COLOR_SNOW - +#ifndef _Definitions_H_ +#define _Definitions_H_ + +const byte weldPin = 2; +const byte weldButtonPin = 4; +const byte upButtonPin = 7; +const byte downButtonPin = 8; +const byte selectButtonPin = 6; +const byte zeroCrossPin = 3; + +const byte TFT_RSTpin = 9; +const byte TFT_RSpin = 10; +const byte TFT_CSpin = 5; + +const int step_ms = 50; +const int sinusMax_us = 4583; // for 50Hz and 60Hz + +#define TXT_COLOR COLOR_YELLOW +#define TXT_COLOR1 COLOR_SNOW + #endif diff --git a/Eeprom.ino b/Eeprom.ino index 824bf5e..9db5649 100644 --- a/Eeprom.ino +++ b/Eeprom.ino @@ -1,31 +1,32 @@ -const unsigned maxWrites = 100; -const unsigned initValue = 123455; // take another value for new initialization +const unsigned maxWrites = 100; +const unsigned initValue = 123; // take another value for new initialization + +void Eeprom::init() +{ setMemPool(0, EEPROMSizeATmega328); + setMaxAllowedWrites(maxWrites); + storedInitValue = getAddress(sizeof(unsigned)); + preweld_ms = getAddress(sizeof(unsigned)); + pause_ms = getAddress(sizeof(unsigned)); + weld_ms = getAddress(sizeof(unsigned)); + orientation = getAddress(sizeof(unsigned)); + if(!initialized()) write(); // fill an empty EEPROM +} + +void Eeprom::read() +{ menuItems[0].upDownVal.value = readInt(preweld_ms); + menuItems[1].upDownVal.value = readInt(pause_ms); + menuItems[2].upDownVal.value = readInt(weld_ms); +} + +void Eeprom::write() +{ writeInt(storedInitValue, initValue); // todo with update()? + writeInt(preweld_ms, menuItems[0].upDownVal.value); + writeInt(pause_ms, menuItems[1].upDownVal.value); + writeInt(weld_ms, menuItems[2].upDownVal.value); + writeInt(orientation, 0); +} + +bool Eeprom::initialized() +{ return readInt(storedInitValue) == initValue; +} -void Eeprom::init() -{ setMemPool(0, EEPROMSizeATmega328); - setMaxAllowedWrites(maxWrites); - storedInitValue = getAddress(sizeof(unsigned)); - preweld_ms = getAddress(sizeof(unsigned)); - pause_ms = getAddress(sizeof(unsigned)); - weld_ms = getAddress(sizeof(unsigned)); - orientation = getAddress(sizeof(unsigned)); - if(!initialized()) write(); // fill an empty EEPROM -} - -void Eeprom::read() -{ menuItems[0].upDownVal.value = readInt(preweld_ms); - menuItems[1].upDownVal.value = readInt(pause_ms); - menuItems[2].upDownVal.value = readInt(weld_ms); -} - -void Eeprom::write() -{ writeInt(storedInitValue, initValue); // todo with update()? - writeInt(preweld_ms, menuItems[0].upDownVal.value); - writeInt(pause_ms, menuItems[1].upDownVal.value); - writeInt(weld_ms, menuItems[2].upDownVal.value); - writeInt(orientation, 0); -} - -bool Eeprom::initialized() -{ return readInt(storedInitValue) == initValue; -} diff --git a/Functions.ino b/Functions.ino index 9013aa8..136cef8 100644 --- a/Functions.ino +++ b/Functions.ino @@ -1,121 +1,85 @@ -void weldControlNoTFT() -{ if(continuously && BCDswitch()==0) weld(weldButton.on()); // continuous welding - else - if(weldButton.pushed()) weldCyclus(BCDswitch() * step_ms); -} - -void weldControlTFT() -{ if(continuously) weld(weldButton.on()); - else - if(weldButton.pushed()) weldCyclus(menuItems[2].upDownVal); -} - -void weldCyclus(int weldTime_ms) -{ if(!sinMaxDisabled) sinusMax(); - pulseWeld(menuItems[0].upDownVal); - delay(menuItems[1].upDownVal); - if(!sinMaxDisabled) sinusMax(); - pulseWeld(weldTime_ms); -} - -int BCDswitch() -{ int bcd; - bitWrite(bcd, 0, !digitalRead(BCDswitch0pin)); - bitWrite(bcd, 1, !digitalRead(BCDswitch1pin)); - bitWrite(bcd, 2, !digitalRead(BCDswitch2pin)); - bitWrite(bcd, 3, !digitalRead(BCDswitch3pin)); - return bcd; -} - -void pulseWeld(int ms) -{ weld(1); - delay(ms); - weld(0); - if(printValuesToSerial) Serial << ms << endl; -} - -void weld(bool b) -{ menu.displayDot(b); - // if (b && !PrevWeld && !sinMaxDisabled) sinusMax(); // If first weld button press, wait on sinus max - digitalWrite(weldPin, b); - digitalWrite(ledPin, !b); - //PrevWeld = b; -} - -void sinusMax() -{ while(digitalRead(zeroCrossPin)); - while(!digitalRead(zeroCrossPin)); - delayMicroseconds(sinusMax_us); // to prevent inrush current, turn-on at the sinus max -} - -void blinkLed(int n) -{ pinMode(ledPin, OUTPUT); - for(byte i=0; i weldButtonPressTime) continuously = 1; - if(!TFTused) continuously &= bcdswitch==0; // bcdswitch has to be at position 0 too -} - -void TFTinit() -{ tft.begin(); - tft.setOrientation(eeprom.readInt(orientation)); - tft.setFont(Terminal12x16); -} - -// Detects if a PCB with or without LCD is being used -bool TFTusedJumper() -{ pinMode(tftJumperOutPin, OUTPUT); // Defines this pin as being an output - pinMode(tftJumperInPin, INPUT_PULLUP); // Defines this pin as being an input with a pull-up resistor - digitalWrite(tftJumperOutPin, 0); - return !digitalRead(tftJumperInPin); // no jumper = 1 (compatible with old software) -} - -void printValuesToSerial() -{ Serial << "\npreweld " << menuItems[0].upDownVal << "ms, pause " << menuItems[1].upDownVal << "ms, weldTime " - << menuItems[2].upDownVal << "ms, continuously " << continuously << endl; -} - -void setOrientation() -{ pollAll(); // works without too - if(upButton.on() && downButton.on()) - { if(eeprom.readInt(orientation)==0) eeprom.writeInt(orientation, 2); // LCD Orientation can only be either 0 or 2 - else eeprom.writeInt(orientation, 0); - } -} +void weldControl() +{ if(continuously) weldContinuously(); + else if(weldButton.pushed()) weldCyclus(menuItems[2].upDownVal); +} + +void weldCyclus(int weldTime_ms) +{ pulseWeld(menuItems[0].upDownVal); + delay(menuItems[1].upDownVal); + pulseWeld(weldTime_ms); +} + +void weldContinuously() +{ if(weldButton.pushed()) sinusMax(); // do only once + weld(weldButton.on()); +} + +void pulseWeld(int ms) +{ sinusMax(); + weld(1); + delay(ms); + weld(0); + if(printValuesToSerial) Serial << ms << endl; +} + +void weld(bool b) +{ menu.displayDot(b); + digitalWrite(weldPin, b); + if(b)Serial << "w "; +} + +void sinusMax() +{ Serial << "sinusMax "; + if(sinMaxDisabled) return; + while(digitalRead(zeroCrossPin)); + while(!digitalRead(zeroCrossPin)); + delayMicroseconds(sinusMax_us); // prevent high inrush current, turn-on at the sinus max +} + +void setpinModes() +{ pinMode(weldButtonPin, INPUT_PULLUP); + pinMode(weldPin, OUTPUT); + pinMode(zeroCrossPin, INPUT); +} + +void pollAll() +{ weldButton.poll(); + upButton.poll(); + downButton.poll(); + selectButton.poll(); +} + +void selectContinuously() +{ const unsigned long switchStable_ms = 200; // min = 50 + const unsigned long weldButtonPressTime = 500; // push weldButton during 500ms at power up + unsigned long start_ms = millis(); + pollAll(); + delay(switchStable_ms); + + while(weldButton.on()) + { pollAll(); + if(!weldButton.on()) break; + } + if(millis()-start_ms > weldButtonPressTime) continuously = 1; +} + +void TFTinit() +{ tft.begin(); + tft.setOrientation(eeprom.readInt(orientation)); + tft.setFont(Terminal12x16); +} + +void printValuesToSerial() +{ Serial << "\npreweld " << menuItems[0].upDownVal << "ms, pause " << menuItems[1].upDownVal << "ms, weldTime " + << menuItems[2].upDownVal << "ms, continuously " << continuously << endl; +} + +void setOrientation() +{ pollAll(); // works without too + if(upButton.on() && downButton.on()) + { if(eeprom.readInt(orientation)==0) eeprom.writeInt(orientation, 2); // LCD Orientation can only be either 0 or 2 + else eeprom.writeInt(orientation, 0); + } +} + diff --git a/README.md b/README.md index 611b070..1318425 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,3 @@ Arduino spot welder controller / solid state relay See the article: http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html - -version 6.2 compiled with the Arduino IDE 1.8.1 should give this output: -------------------------------------------------------------------------- -Sketch uses 14470 bytes (44%) of program storage space. Maximum is 32256 bytes. -Global variables use 792 bytes (38%) of dynamic memory, leaving 1256 bytes for local variables. Maximum is 2048 bytes. -------------------------------------------------------------------------- diff --git a/Spotwelder-SMD.ino b/Spotwelder-SMD.ino new file mode 100644 index 0000000..412c520 --- /dev/null +++ b/Spotwelder-SMD.ino @@ -0,0 +1,81 @@ +// Warning, set sinMaxDisabled = 0 for the production firmware +bool sinMaxDisabled = 1; // Set this 0 for testing without transformer + +/* +Note: use the latest Arduino software and install the libraries. + +Arduino spot welder controller +http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html + +Copyright (C) 2012 Albert van Dalen +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . +Version 5.2 1-02-2015 +Version 6.0 2-01-2017 added menu with TFT display +Version 6.1 22-05-2017 added set display orientation +Version 6.2 26-8-2017 only supports PCB with LCD now, weldContinuously with sinusMax, displayDot improved + +Program with FTDI programmer, Extra > Board > Arduino Uno + + < 20ms >< >sinusMax_us + _____ _____ _____ +zeroCross __| |_____| |_____| |__ + _____________ +weld __________________| |____ + +T = 1/(4*50Hz) = 5000us +T = 1/(4*60Hz) = 4167us +Average time: sinusMax_us = (5000us + 4167us)/2 = 4583us, is not critical, use for 50 and 60Hz +*/ + +#include +#include +#include +#include // todo for ILI9341 240 x 320 +#include +#include +#include +#include "Definitions.h" +#include "Classes.h" +#include "Eeprom.h" + +String version = "Version 6.2"; + +Switch weldButton(weldButtonPin); +Switch upButton(upButtonPin); +Switch downButton(downButtonPin); +Switch selectButton(selectButtonPin); +TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // use hardware SPI +UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 +Menu menu; +Eeprom eeprom; +// Defines the main menu entry names/items +MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue +MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(500, 50, 0, 1000)); +MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 0, 1000)); +MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; + +bool continuously; +unsigned orientation; + +void setup() +{ Serial.begin(9600); + eeprom.init(); + eeprom.read(); + setpinModes(); + setOrientation(); // LCD orientation is random, do after eeprom.init() + TFTinit(); + selectContinuously(); + printValuesToSerial(); + menu.displayAll(); +} + +void loop() +{ pollAll(); + menu.control(); + weldControl(); +} + + From e4fb14e35c9652c0f35f65bd4d89211f4f3f1e23 Mon Sep 17 00:00:00 2001 From: candidol <31170621+candidol@users.noreply.github.com> Date: Tue, 29 Aug 2017 21:09:07 +0100 Subject: [PATCH 14/19] Delete Spotwelder-6.2.ino --- Spotwelder-6.2.ino | 91 ---------------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 Spotwelder-6.2.ino diff --git a/Spotwelder-6.2.ino b/Spotwelder-6.2.ino deleted file mode 100644 index a8dc378..0000000 --- a/Spotwelder-6.2.ino +++ /dev/null @@ -1,91 +0,0 @@ -// Warning, set sinMaxDisabled = 0 for the production firmware -bool sinMaxDisabled = 1; // Set this 0 for testing without transformer - -/* -Note: use the latest Arduino software and install the libraries. - -Arduino spot welder controller -http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html - -Copyright (C) 2012 Albert van Dalen -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . -Version 5.2 1-02-2015 -Version 6.0 2-01-2017 added menu with TFT display -Version 6.1 22-05-2017 added set display orientation - -Program with FTDI programmer, Extra > Board > Arduino Uno - - < 20ms >< >sinusMax_us - _____ _____ _____ -zeroCross __| |_____| |_____| |__ - _____________ -weld __________________| |____ - -T = 1/(4*50Hz) = 5000us -T = 1/(4*60Hz) = 4167us -Average time sinusMax_us = (5000us + 4167us)/2 = 4583us, this does not have to be exact -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "Definitions.h" -#include "Classes.h" -#include "Eeprom.h" - -String version = "Version 6.2"; - -Switch weldButton(weldButtonPin); -Switch upButton(upButtonPin); -Switch downButton(downButtonPin); -Switch selectButton(selectButtonPin); -TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // hardware SPI -// Defines the main menu entry names/items -MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue -MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(500, 50, 0, 1000)); -MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 0, 1000)); -MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; -UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 -Menu menu; -Eeprom eeprom; - -bool TFTused; -bool continuously; -//bool PrevWeld; -unsigned orientation; - -void setup() -{ Serial.begin(9600); - eeprom.init(); - eeprom.read(); - setpinModes(); - // eeprom.writeInt(orientation, 2); / for new PCB with TFT - - // For old PCB with or without TFT: - TFTused = TFTusedJumper(); - setOrientation(); // do after eeprom.init() - if(TFTused) TFTinit(); - if(!TFTused) blinkLed(4); - - digitalWrite(ledPin, 1); // power on indication - selectContinuously(); - printValuesToSerial(); - if(TFTused) menu.displayAll(); -} - -void loop() -{ pollAll(); - if(TFTused) - { menu.control(); - weldControlTFT(); - } else - weldControlNoTFT(); -} - From cc3b3609bc073dd0ace929b22f9789049b178a0c Mon Sep 17 00:00:00 2001 From: candidol <31170621+candidol@users.noreply.github.com> Date: Tue, 29 Aug 2017 21:40:44 +0100 Subject: [PATCH 15/19] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 1318425..774dc98 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,9 @@ Arduino spot welder controller / solid state relay See the article: http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html + +When this project is compiled with the Arduino 1.8.1 IDE, the following compilation result should be output: +----------------------------------------------------------------------------------------------- +Sketch uses 14228 bytes (44%) of program storage space. Maximum is 32256 bytes. +Global variables use 820 bytes (40%) of dynamic memory, leaving 1228 bytes for local variables. Maximum is 2048 bytes. +---------------------------------------------------------------------------------------------- From 1eb90c77df936cefb2beeaff5e6ae10c15423b8d Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Sun, 31 Dec 2017 12:06:00 +0100 Subject: [PATCH 16/19] Add files via upload --- Classes.h | 18 +++++--- Classes.ino | 104 +++++++++++++++++++++++++++------------------ Definitions.h | 23 +++++----- Eeprom.h | 2 +- Eeprom.ino | 33 +++++++------- Functions.ino | 69 +++++++++++++++--------------- Spotwelder-7.1.ino | 96 +++++++++++++++++++++++++++++++++++++++++ tests.ino | 7 +++ 8 files changed, 240 insertions(+), 112 deletions(-) create mode 100644 Spotwelder-7.1.ino create mode 100644 tests.ino diff --git a/Classes.h b/Classes.h index 9fe775b..c6fb51e 100644 --- a/Classes.h +++ b/Classes.h @@ -27,16 +27,20 @@ class MenuItem class Menu { public: + void displayStart(); void control(); - void displayAll(); - void displayName(int itemNr, String &name); - void displayValue(int itemNr, int value, bool focus, bool background); void displayDot(bool on); - void drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor=COLOR_BLACK); - + void TFTinit(); + private: - bool editValue=0; - const int txtLeft = 17; + void displayName(int itemNr, String &name); + void displayValue(int itemNr, int value, bool focus, bool edit); + void drawColorTextLine(int line, int left, String str, uint16_t textColor=TFT_WHITE, uint16_t backgroundColor=TFT_BLACK); // line 0..8 + void displayContinuously(); + + bool editValueMode=0; + const int textLeft = 20, fontSize=4, fontHeight=26; + const int vertOffset=3; // 240-9*26)/2 }; #endif diff --git a/Classes.ino b/Classes.ino index 153485d..17dcbb1 100644 --- a/Classes.ino +++ b/Classes.ino @@ -1,81 +1,91 @@ #include "Classes.h" #include -void Menu::drawColorTextLine(int line, int left, String str, uint16_t color=COLOR_WHITE, uint16_t backgroundColor) -{ tft.fillRectangle(left, 20*line, 175, 20*line+19, backgroundColor); // line <= 10 - tft.setBackgroundColor(backgroundColor); - tft.drawText(left, 20*line+2, str, color); -} - void Menu::control() -{ if(!editValue) +{ if(!editValueMode) { if(upButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item - menu.displayValue(upDownItemNr, menuItems[upDownItemNr.down()].upDownVal, 1, editValue); // focus + { displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal, 0, editValueMode); // un-focus old item + displayValue(WeldItemNr, menuItems[WeldItemNr.down()].upDownVal, 1, editValueMode); // focus return; } if(downButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, editValue); // un-focus old item - menu.displayValue(upDownItemNr, menuItems[upDownItemNr.up()].upDownVal, 1, editValue); // focus + { displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal, 0, editValueMode); // un-focus old item + displayValue(WeldItemNr, menuItems[WeldItemNr.up()].upDownVal, 1, editValueMode); // focus return; } if(selectButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=1); // add backgound + { displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal, 1, editValueMode=1); // add backgound return; } - } - if(editValue) + } + + if(editValueMode) { if(upButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.up(), 1, editValue); + { displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal.up(), 1, editValueMode); return; } if(downButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal.down(), 1, editValue); + { displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal.down(), 1, editValueMode); return; } if(selectButton.pushed()) - { menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, editValue=0); // delete backgound + { displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal, 1, editValueMode=0); // delete backgound eeprom.write(); return; } } } -void Menu::displayAll() -{ displayName(0, version); - delay(500); - +void Menu::displayStart() +{ drawColorTextLine(0, textLeft, version, TFT_YELLOW); + delay(1000); + TFTinit(); + if(!continuously) { for(int i=0; i<3; i++) - { upDownItemNr.value=i; - displayName(upDownItemNr, menuItems[upDownItemNr].name); - menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 0, 0); - } - upDownItemNr.value = 0; - menu.displayValue(upDownItemNr, menuItems[upDownItemNr].upDownVal, 1, 0); // item 0 has focus + { WeldItemNr.value=i; + displayName(WeldItemNr, menuItems[WeldItemNr].name); + displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal, 0, 0); + } + WeldItemNr.value = 0; + displayValue(WeldItemNr, menuItems[WeldItemNr].upDownVal, 1, 0); // item 0 has focus displayDot(0); - drawColorTextLine(10, 0, "- + sel weld", COLOR_YELLOW, COLOR_BLUEVIOLET); // todo no weld button text - } - else - { drawColorTextLine(4, 0, " Continuously", COLOR_WHITE, COLOR_RED); - drawColorTextLine(5, 0, " mode", COLOR_WHITE, COLOR_RED); - drawColorTextLine(6, 0, " Take care!", COLOR_WHITE, COLOR_RED); - drawColorTextLine(10, 0, " Weld", COLOR_YELLOW, COLOR_BLUEVIOLET); // todo no weld button text + drawColorTextLine(8, 0, " down up sel ", TFT_YELLOW, TFT_BLUE); // to long text is ok } + else displayContinuously(); } - + +void Menu::displayContinuously() +{ tft.fillScreen(TFT_RED); + drawColorTextLine(2, 0, " Continuously", TFT_WHITE, TFT_RED); + drawColorTextLine(3, 0, " mode", TFT_WHITE, TFT_RED); + drawColorTextLine(4, 0, " Take care!", TFT_WHITE, TFT_RED); + displayDot(0); +} + void Menu::displayDot(bool on) -{ tft.fillCircle(87, 170, 12, on? COLOR_RED : COLOR_DARKGREEN); +{ tft.fillCircle(148, 180, 20, on? TFT_WHITE : 0x64A7/*green*/); // https://ee-programming-notepad.blogspot.nl/2016/10/16-bit-color-generator-picker.html +} + +void Menu::drawColorTextLine(int line, int left, String str, uint16_t textColor, uint16_t backgroundColor) +{ tft.setTextColor(textColor, backgroundColor); + tft.drawString(str.c_str(), left, fontHeight*line+vertOffset, fontSize); } -void Menu::displayName(int upDownItemNr, String &name) -{ drawColorTextLine(2*upDownItemNr, txtLeft, name, TXT_COLOR); +void Menu::displayName(int WeldItemNr, String &name) +{ drawColorTextLine(2*WeldItemNr, textLeft, name, TFT_YELLOW); } -void Menu::displayValue(int upDownItemNr, int value, bool focus, bool background) -{ menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(" ")); // clear line - menu.drawColorTextLine(2*upDownItemNr+1, 0, focus? ">" : " ", TXT_COLOR1); - menu.drawColorTextLine(2*upDownItemNr+1, txtLeft, String(value), background? COLOR_BLACK : TXT_COLOR1, background? COLOR_CYAN : COLOR_BLACK); +void Menu::displayValue(int WeldItemNr, int value, bool focus, bool edit) +{ drawColorTextLine(2*WeldItemNr+1, textLeft, " ", TFT_WHITE); // clear line, can't be BLACK (bug?) + drawColorTextLine(2*WeldItemNr+1, 0, ">", focus? TFT_WHITE : TFT_BLACK); // BLACK on BLACK = BLACK + drawColorTextLine(2*WeldItemNr+1, textLeft, String(value), edit? TFT_BLACK : TFT_WHITE, edit? TFT_CYAN : TFT_BLACK); +} + +void Menu::TFTinit() +{ tft.init(); + tft.setRotation(orientation); + tft.fillScreen(TFT_BLACK); } // --------------------------------------------------------------------------- @@ -106,4 +116,14 @@ name(name), upDownVal(value) { } +/* + if(downButton.on() && selectButton.on()) + { preferencesControl(); + return; + } + + drawColorTextLine(2, textLeft, "Set preferences:", TFT_YELLOW); + drawColorTextLine(3, textLeft, "press down + sel", TFT_YELLOW); +*/ + diff --git a/Definitions.h b/Definitions.h index c876ff8..4f79f77 100644 --- a/Definitions.h +++ b/Definitions.h @@ -1,21 +1,20 @@ #ifndef _Definitions_H_ #define _Definitions_H_ -const byte weldPin = 2; -const byte weldButtonPin = 4; -const byte upButtonPin = 7; +const byte weldPin = 5; +const byte ledPin = A3; +const byte weldButtonPin = 7; +const byte upButtonPin = 9; const byte downButtonPin = 8; -const byte selectButtonPin = 6; -const byte zeroCrossPin = 3; +const byte selectButtonPin = 10; +const byte foodSwitchPin = A5; +const byte zeroCrossPin = 2; -const byte TFT_RSTpin = 9; -const byte TFT_RSpin = 10; -const byte TFT_CSpin = 5; +const byte TFT_RSTpin = A1; // set in user.h, todo: do in TFT_ILI9341 constructor +const byte TFT_DCpin = A0; +const byte TFT_CSpin = A2; const int step_ms = 50; -const int sinusMax_us = 4583; // for 50Hz and 60Hz - -#define TXT_COLOR COLOR_YELLOW -#define TXT_COLOR1 COLOR_SNOW +const int sinusMax_us = 4583; // average between 0.25/50Hz and 0.25/60Hz #endif diff --git a/Eeprom.h b/Eeprom.h index 9a7e044..11c3eac 100644 --- a/Eeprom.h +++ b/Eeprom.h @@ -6,5 +6,5 @@ class Eeprom: public EEPROMClassEx void write(); bool initialized(); - unsigned storedInitValue, preweld_ms, pause_ms, weld_ms; // EEPROM addresses + unsigned storedInitValue_addr, preweld_ms_addr, pause_ms_addr, weld_ms_addr; // EEPROM addresses }; diff --git a/Eeprom.ino b/Eeprom.ino index 9db5649..0eb8659 100644 --- a/Eeprom.ino +++ b/Eeprom.ino @@ -1,32 +1,33 @@ const unsigned maxWrites = 100; -const unsigned initValue = 123; // take another value for new initialization +const unsigned initValue = 4; // take another value for factory default settings void Eeprom::init() { setMemPool(0, EEPROMSizeATmega328); setMaxAllowedWrites(maxWrites); - storedInitValue = getAddress(sizeof(unsigned)); - preweld_ms = getAddress(sizeof(unsigned)); - pause_ms = getAddress(sizeof(unsigned)); - weld_ms = getAddress(sizeof(unsigned)); - orientation = getAddress(sizeof(unsigned)); - if(!initialized()) write(); // fill an empty EEPROM + storedInitValue_addr = getAddress(sizeof(unsigned)); + preweld_ms_addr = getAddress(sizeof(unsigned)); + pause_ms_addr = getAddress(sizeof(unsigned)); + weld_ms_addr = getAddress(sizeof(unsigned)); + orientation_addr = getAddress(sizeof(unsigned)); + if(!initialized()) write(); // fill an empty EEPROM with factory default settings } void Eeprom::read() -{ menuItems[0].upDownVal.value = readInt(preweld_ms); - menuItems[1].upDownVal.value = readInt(pause_ms); - menuItems[2].upDownVal.value = readInt(weld_ms); +{ menuItems[0].upDownVal.value = readInt(preweld_ms_addr); + menuItems[1].upDownVal.value = readInt(pause_ms_addr); + menuItems[2].upDownVal.value = readInt(weld_ms_addr); + orientation = readInt(orientation_addr); } void Eeprom::write() -{ writeInt(storedInitValue, initValue); // todo with update()? - writeInt(preweld_ms, menuItems[0].upDownVal.value); - writeInt(pause_ms, menuItems[1].upDownVal.value); - writeInt(weld_ms, menuItems[2].upDownVal.value); - writeInt(orientation, 0); +{ writeInt(storedInitValue_addr, initValue); + writeInt(preweld_ms_addr, menuItems[0].upDownVal.value); + writeInt(pause_ms_addr, menuItems[1].upDownVal.value); + writeInt(weld_ms_addr, menuItems[2].upDownVal.value); + writeInt(orientation_addr, orientation); } bool Eeprom::initialized() -{ return readInt(storedInitValue) == initValue; +{ return readInt(storedInitValue_addr) == initValue; } diff --git a/Functions.ino b/Functions.ino index 136cef8..a40649b 100644 --- a/Functions.ino +++ b/Functions.ino @@ -1,6 +1,28 @@ +void selectTFTorientation() // because LCD orientation is unknown +{ if(upButton.on() && downButton.on()) // change between 1<->3 when up and down are pressed during power up + { if(orientation==1) orientation=3; // orientation can only be either 1 or 3 + else orientation=1; // if 0, 2, 3... + eeprom.write(); + } +} + +void selectContinuously() +{ const unsigned long switchStable_ms = 200; // min = 50 + const unsigned long weldButtonPressTime = 500; // push weldButton during 500ms at power up + unsigned long start_ms = millis(); + pollAll(); + delay(switchStable_ms); + + while(weldButton.on()) + { pollAll(); + if(!weldButton.on()) break; + } + if(millis()-start_ms > weldButtonPressTime) continuously = 1; +} + void weldControl() { if(continuously) weldContinuously(); - else if(weldButton.pushed()) weldCyclus(menuItems[2].upDownVal); + else if(weldButton.pushed() || foodSwitch.pushed()) weldCyclus(menuItems[2].upDownVal); } void weldCyclus(int weldTime_ms) @@ -10,22 +32,22 @@ void weldCyclus(int weldTime_ms) } void weldContinuously() -{ if(weldButton.pushed()) sinusMax(); // do only once +{ if(weldButton.pushed()) sinusMax(); // do only once weld(weldButton.on()); } void pulseWeld(int ms) { sinusMax(); - weld(1); + if(ms) weld(1); // avoid short displayDot flash delay(ms); weld(0); - if(printValuesToSerial) Serial << ms << endl; + Serial << ms << endl; } void weld(bool b) { menu.displayDot(b); digitalWrite(weldPin, b); - if(b)Serial << "w "; + if(b) Serial << "w "; } void sinusMax() @@ -37,9 +59,14 @@ void sinusMax() } void setpinModes() -{ pinMode(weldButtonPin, INPUT_PULLUP); +{ pinMode(upButtonPin, INPUT_PULLUP); + pinMode(downButtonPin, INPUT_PULLUP); + pinMode(selectButtonPin, INPUT_PULLUP); + pinMode(weldButtonPin, INPUT_PULLUP); pinMode(weldPin, OUTPUT); + pinMode(ledPin, OUTPUT); // is also done in blinkLed pinMode(zeroCrossPin, INPUT); + pinMode(foodSwitchPin, INPUT_PULLUP); } void pollAll() @@ -47,39 +74,13 @@ void pollAll() upButton.poll(); downButton.poll(); selectButton.poll(); -} - -void selectContinuously() -{ const unsigned long switchStable_ms = 200; // min = 50 - const unsigned long weldButtonPressTime = 500; // push weldButton during 500ms at power up - unsigned long start_ms = millis(); - pollAll(); - delay(switchStable_ms); - - while(weldButton.on()) - { pollAll(); - if(!weldButton.on()) break; - } - if(millis()-start_ms > weldButtonPressTime) continuously = 1; -} - -void TFTinit() -{ tft.begin(); - tft.setOrientation(eeprom.readInt(orientation)); - tft.setFont(Terminal12x16); + foodSwitch.poll(); } void printValuesToSerial() { Serial << "\npreweld " << menuItems[0].upDownVal << "ms, pause " << menuItems[1].upDownVal << "ms, weldTime " - << menuItems[2].upDownVal << "ms, continuously " << continuously << endl; + << menuItems[2].upDownVal << "ms, continuously " << continuously << ", Orientation " << orientation << endl; } -void setOrientation() -{ pollAll(); // works without too - if(upButton.on() && downButton.on()) - { if(eeprom.readInt(orientation)==0) eeprom.writeInt(orientation, 2); // LCD Orientation can only be either 0 or 2 - else eeprom.writeInt(orientation, 0); - } -} diff --git a/Spotwelder-7.1.ino b/Spotwelder-7.1.ino new file mode 100644 index 0000000..62296af --- /dev/null +++ b/Spotwelder-7.1.ino @@ -0,0 +1,96 @@ +bool sinMaxDisabled = 0; // 0 for production firmware, 1 for test without transformer +/* +Attention: verify code after upload: ON / OFF + +Todo +Change maximum values, just as selectTFTorientation() + +Note: use the latest Arduino software and install the libraries. + +Arduino spot welder controller +http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html + +Copyright (C) 2012 Albert van Dalen +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . + +TFT 240x320 library: +https://www.instructables.com/id/Arduino-TFT-display-and-font-library/ +https://github.com/Bodmer/TFT_ILI9341 m + +Version 5.2 1-02-2015 +Version 6.0 2-01-2017 added menu with TFT display +Version 6.1 22-05-2017 added set display orientation +Version 6.2 26-8-2017 only supports PCB with LCD now, weldContinuously with sinusMax, displayDot improved +Version 7.0 2-10-2017 only for smd board and ILI9341 240x320 TFT display + +Program with FTDI programmer, Extra > Board > Arduino Uno + + < 20ms >< >sinusMax_us + _____ _____ _____ +zeroCross __| |_____| |_____| |__ + _____________ +weld __________________| |____ + +T = 1/(4*50Hz) = 5000us +T = 1/(4*60Hz) = 4167us +Average time: sinusMax_us = (5000us + 4167us)/2 = 4583us, is not critical, use for 50 and 60Hz +*/ + +#include +#include +#include +#include // // https://github.com/Bodmer/TFT_ILI9341 disadvantage: settings in library + +#include +#include +#include +#include "Definitions.h" +#include "Classes.h" +#include "Eeprom.h" + +String version = "Version 7.1"; + +Switch weldButton(weldButtonPin); +Switch upButton(upButtonPin); +Switch downButton(downButtonPin); +Switch selectButton(selectButtonPin); +Switch foodSwitch(foodSwitchPin); + +TFT_ILI9341 tft = TFT_ILI9341(); // pins defined in User_Setup.h +UpDownValue WeldItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 + +Menu menu; +Eeprom eeprom; +// Set the menu item DEFAULT values: value, step, minValue, maxValue +MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); +MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(500, 50, 0, 1000)); +MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 0, 1000)); +MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; + +bool continuously; +unsigned orientation_addr, orientation=3; + +void setup() +{ Serial.begin(9600); + setpinModes(); + pollAll(); + blinkLed(ledPin, 3); // is a delay too + pollAll(); // do after the blinkLed() delay + eeprom.init(); + eeprom.read(); // set the menu with the stored EEPROM values + selectTFTorientation(); // do after eeprom.init and before TFTinit() + selectContinuously(); + menu.TFTinit(); + printValuesToSerial(); + menu.displayStart(); +} + +void loop() +{ pollAll(); + menu.control(); + weldControl(); + // test(); +} diff --git a/tests.ino b/tests.ino new file mode 100644 index 0000000..04bff81 --- /dev/null +++ b/tests.ino @@ -0,0 +1,7 @@ +#include "avdweb_VirtualDelay.h" +VirtualDelay testDelay; // default = millis + +void test() +{ testDelay.start(10000); // weld every 10s + if(testDelay.elapsed()) weldCyclus(menuItems[2].upDownVal); +} From 588c0f3f8c443b94c428792828e3171ef86a20b7 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Sun, 31 Dec 2017 12:07:37 +0100 Subject: [PATCH 17/19] Delete Spotwelder-SMD.ino --- Spotwelder-SMD.ino | 81 ---------------------------------------------- 1 file changed, 81 deletions(-) delete mode 100644 Spotwelder-SMD.ino diff --git a/Spotwelder-SMD.ino b/Spotwelder-SMD.ino deleted file mode 100644 index 412c520..0000000 --- a/Spotwelder-SMD.ino +++ /dev/null @@ -1,81 +0,0 @@ -// Warning, set sinMaxDisabled = 0 for the production firmware -bool sinMaxDisabled = 1; // Set this 0 for testing without transformer - -/* -Note: use the latest Arduino software and install the libraries. - -Arduino spot welder controller -http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html - -Copyright (C) 2012 Albert van Dalen -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses . -Version 5.2 1-02-2015 -Version 6.0 2-01-2017 added menu with TFT display -Version 6.1 22-05-2017 added set display orientation -Version 6.2 26-8-2017 only supports PCB with LCD now, weldContinuously with sinusMax, displayDot improved - -Program with FTDI programmer, Extra > Board > Arduino Uno - - < 20ms >< >sinusMax_us - _____ _____ _____ -zeroCross __| |_____| |_____| |__ - _____________ -weld __________________| |____ - -T = 1/(4*50Hz) = 5000us -T = 1/(4*60Hz) = 4167us -Average time: sinusMax_us = (5000us + 4167us)/2 = 4583us, is not critical, use for 50 and 60Hz -*/ - -#include -#include -#include -#include // todo for ILI9341 240 x 320 -#include -#include -#include -#include "Definitions.h" -#include "Classes.h" -#include "Eeprom.h" - -String version = "Version 6.2"; - -Switch weldButton(weldButtonPin); -Switch upButton(upButtonPin); -Switch downButton(downButtonPin); -Switch selectButton(selectButtonPin); -TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RSTpin, TFT_RSpin, TFT_CSpin, 0); // use hardware SPI -UpDownValue upDownItemNr = UpDownValue(0, 1, 0, 2); // 3 items 0 1 2 -Menu menu; -Eeprom eeprom; -// Defines the main menu entry names/items -MenuItem preweldTimeItem = MenuItem("Preweld, ms", UpDownValue(50, 50, 0, 1000)); // value, step, minValue, maxValue -MenuItem pauseTimeItem = MenuItem("Pause, ms", UpDownValue(500, 50, 0, 1000)); -MenuItem weldTimeItem = MenuItem("Weld time, ms", UpDownValue(250, 50, 0, 1000)); -MenuItem menuItems[] = {preweldTimeItem, pauseTimeItem, weldTimeItem}; - -bool continuously; -unsigned orientation; - -void setup() -{ Serial.begin(9600); - eeprom.init(); - eeprom.read(); - setpinModes(); - setOrientation(); // LCD orientation is random, do after eeprom.init() - TFTinit(); - selectContinuously(); - printValuesToSerial(); - menu.displayAll(); -} - -void loop() -{ pollAll(); - menu.control(); - weldControl(); -} - - From f76089dfd46300b0e2631447c211bba19f7d79f3 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Sun, 31 Dec 2017 12:07:52 +0100 Subject: [PATCH 18/19] Delete Install these libraries.zip --- Install these libraries.zip | Bin 30392 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Install these libraries.zip diff --git a/Install these libraries.zip b/Install these libraries.zip deleted file mode 100644 index 4445a5a76c59f7d8bee9e974d5f9806a298d483d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30392 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 C2c|Uu From 83cbbbbd6c14f197a0de6229a213da4e94bf55b6 Mon Sep 17 00:00:00 2001 From: Albert van Dalen Date: Sun, 31 Dec 2017 12:08:41 +0100 Subject: [PATCH 19/19] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index 774dc98..1318425 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,3 @@ Arduino spot welder controller / solid state relay See the article: http://www.avdweb.nl/arduino/hardware-interfacing/spot-welder-controller.html - -When this project is compiled with the Arduino 1.8.1 IDE, the following compilation result should be output: ------------------------------------------------------------------------------------------------ -Sketch uses 14228 bytes (44%) of program storage space. Maximum is 32256 bytes. -Global variables use 820 bytes (40%) of dynamic memory, leaving 1228 bytes for local variables. Maximum is 2048 bytes. -----------------------------------------------------------------------------------------------