MIG to TIG Welder Controller

Purpose: To generate an adjustable AC Square wave from a DC source for the purpose of welding aluminum.

Aluminum develops a stubborn oxide layer. To combat this, TIG welders use an AC square wave. The ‘push’ does the welding, and the pull breaks the oxide layer. A preferable wave will be 70% push, and 30% pull. The frequency should be adjustable from around 60HZ to 125HZ. But a brief high frequency ark starting pulse is used momentarily. Amperage should also be controlled by a foot pedal.

This code attempts to achieve this. It uses one POT to set the ‘push or up’ pulse width, and another to set the pull or low PW. The lower is expressed as a percentage of the first.

The sketch begins when a switch in the foot pedal is triggered. It sends signal to turn on power and open the gas solenoid in the MIG welder. It also triggers the start pulse which should be 333KHZ for 3mS. Then it should move on to output the set frequency and PW. The high and low PW will each go to a separate POT in the foot pedal and then the up to a bank of MOSFETS for the up pulse, and the low output to a matching bank for the lower pulse.

The foot pedal POTs will modify the voltage sent to the MOSFET gates and thus control amperage. I may add an OP amp to these signals. This should give me a bi-polar AC square wave with adjustable PW above and below the 0V line.

This is a work in progress. I am uploading what I have so far. I still need to add outputs for the displays. The upper will show HZ of the wave. And the lower will show the percentage for the low wave. I think I’m pretty close to a working sketch though.

I’m not super experienced with this stuff so if anyone wishes to contribute, that would be great. Units that will do all this are stupid expensive, But DC welders are cheap. Let me know what you think. PS I’m using while loops because I want it to stay put until it shouldn’t.

const int UpOutPin = 9;   // Sends upper PW through pedal POT 1 and to up MOSFET gate
const int UpPotPin = A0;  // Reads upper PW time from upper POT
const int LowOutPin = 8;  // Sends low PW through pedal POT 2 and to down MOSFET gate
const int LowPotPin = A1; // Reads low PW POT - value of which will be a percentage of up PW. 
const int PedalPin = 7;   // Pedal main switch
const int OnSig = 6;      // Sends on signal to power source and gas valve.

//Variables:
int value; //save analog value
void setup(){
 //Upper Pulse
 pinMode(UpOutPin, OUTPUT); // To Pedal Pot 1 in then up MOSFET gate
 pinMode(UpPotPin, INPUT);  // From up POT
 //Lower Pulse
 pinMode (LowOutPin, OUTPUT); // To Peedal Pot then down MOSFTET gate.
 pinMode (LowPotPin, INPUT);  // From low POT
 // Foot Peddal
 pinMode (PedalPin, INPUT);
 pinMode (Trigger, INPUT);
 // Main on
 pinMode (OnSig, OUTPUT);
}
void loop()
{

 // Startup Wave - must run one time each time the foot pedal is first pressed, then exit go to static wave below,
if (PedalPin, LOW)  //Pedal Switch
{
 count = 0
  while (PedalPin, HIGH && count < 10000)  // outputs 333KHZ wave for 0.03 seconds (10,000) loops.
 {    count = count++
      digitalWrite (OnSig, HIGH);
      digitalWrite (UpOutPin, HIGH);
      delay (.001)
      digitalWrite (UpOutPin, LOW);
      delay (.001)
      digitalWrite (LowOutPin, HIGH);
      delay (.001)
      digitalWrite (LowOutPin, LOW);
     
}
}

while (PedalPin, HIGH)
{

 digitalWrite (OnSig, HIGH);         // Powers up gas valave and power supply
 
 // Upper Pulse
 value = analogRead(UpPotPin);          //Read and save analog value from potentiometer
 UPwidth = map(value, 0, 1023, 2.5, 25); //Map value 0-1023 to 0-25 (width of up pulse 400Hz - 40Hz)
 digitalWrite(UpOutPin, HIGH);          //Send up pulse out from pin
 delay(Upwidth);                          //Small delay
 digitalwrite(UpOutPin, LOW);             // Turn off

 //Lower Pulse

 Value = analogRead (LowPotPin);
 Low_width = map (value, 0, 1023, .1, 1);  // Low pulsewidth percentage of high pulsewidth
 digitalwrite (LowOutPin, HIGH);
 LwPercent = (Low_width*Upwidth);
 delay (LwPercent);
 digitalWrite(LowOutPin, LOW):
 
}


}

TIG.ino (2.31 KB)

So… basically you have an adjustable square wave. Adjusting how often it hits (period) “60HZ to 125HZ” and adjusting percent of the “push%” (pulse %) “70% push, and 30% pull” These adjustments are from reading Pots.

I get that right? Is this the logic of what you’re looking for?

-jim lee

Basically. With a little more to it. I set it up for 40HZ to 400Hz just because. And a 330KHZ 30 mill startup. Plus an output signal that triggers the MIG output and gas solenoid.

Hmm… Is my math correct that you are looking for a frequency period of 3.03 microseconds for 30 milliseconds? What kind of tolerance is there on that higher frequency? Would something around 300KHZ work? 2 micros on 1 micro off.

-jim lee

Please post your code within </> code-tags (and remove any excess white lines and format using ctrl-T ) delay (.001)?? delay takes an unsigned long, you must mean delayMicroseconds() (and you missed a semicolon)
I think the starting pulse should be done using direct port manipulation (for the sake of speed).
And then i would use PWM for the normal pulse (easy to adjust) That means you will just have to lower the PWM frequency a little, and you will be able to monitor the switch (and pots) through polling (or interrupts) but nothing will interfere with the pulse.

Its Covid and I’m dying of boredom…

So… I had a shot at writing a framework to your spec. At least as far as I could understand it. If it helps? Cool! If not. Oh well, it kept me busy for a while. :slight_smile:

It compiles, who knows if it’ll work? If you want to try it you will need to install LC_baseTools using the IDE’s library manager.

Good luck!

-jim lee

forum_post.ino (9.16 KB)

It's going to take me a bit to figure out what you did. I'm pretty new at this. Thanks though.

jimLee:
Hmm.. Is my math correct that you are looking for a frequency period of 3.03 microseconds for 30 milliseconds? What kind of tolerance is there on that higher frequency? Would something around 300KHZ work? 2 micros on 1 micro off.

-jim lee

Right. Those figures will require some experiment. There is a high frequency pulse to create the initial ark. Once the ark is established, it drops to a more suitable wave which would typically be 60HZ to 120HZ. The PW of the up and down peaks need to be adjustable. Most welding is done with 70% spent in the up, and 30% spent in the down. Weld - clean - weld -clean.

It could be a few thousand HZ off but I don't want to be too fast for the MOSFET.

Deva_Rishi:
Please post your code within </> code-tags (and remove any excess white lines and format using ctrl-T )

 delay (.001)

?? delay takes an unsigned long, you must mean delayMicroseconds() (and you missed a semicolon)
I think the starting pulse should be done using direct port manipulation (for the sake of speed).
And then i would use PWM for the normal pulse (easy to adjust) That means you will just have to lower the PWM frequency a little, and you will be able to monitor the switch (and pots) through polling (or interrupts) but nothing will interfere with the pulse.

It’s not done yet. Yes, I am delaying microseconds for the start up pulse. After that, I need to be able to set the time of the above 0 pulses separate from the below 0 pulses. It’s usually 70% + PW to 30% - PW. I will look into direct port manipulation. I don’t know it right now. And I don’t know how to manipulate the board PWM directly and to make the up be 180 out of phase with the down. I figure at typical rate of 120HZ max, I’m not straining anything.

And I don't know how to manipulate the board PWM directly and to make the up be 180 out of phase with the down.

It explains here how to set the PWM frequency, and 122Hz is available for 4 of the 6 pwm pins, that should suit you. I suppose you'll be driving one mosfet normal logic, and the other inverted logic. Once you've set the pwm frequency all you need to do is set the duty cycle to 70% something like analogWrite(pin, 180);
Direct port manipulation is described here. DigitalWrite() is quite slow because it checks for the pin used as a PWM pin. Of course since you will be doing that you will have to make sure that before the initial pulse you do analogWrite(pin, 0); or do one digitalWrite(pin LOW);Of course you could also just use the PWM to do the initial pulse, since you can set it for a frequency up to 31372.55 Hz, but that is only about a 10th of the speed you desire. Will you mosfets be quick enough for 300KHz ?

jimLee:
Its Covid and I’m dying of boredom…

So… I had a shot at writing a framework to your spec. At least as far as I could understand it. If it helps? Cool! If not. Oh well, it kept me busy for a while. :slight_smile:

It compiles, who knows if it’ll work? If you want to try it you will need to install LC_baseTools using the IDE’s library manager.

Good luck!

-jim lee

Well this certainly inspired me to learn about libraries. I think I need to add these libraries from what I understand. Where would I find the files I need to add?

So I modified my initial code from your previous post and made it a "library" you can include on your sketch

Just copy the two attached files tigpwm.c and tigpwm.h on your sketch folder

aaa.png

Try this code on your Arduino to test

#include "tigpwm.h"

void setup() {

  // setup D9 and D10 as complimentary PWM outputs
  TIGPWM_init();

  // generate 120 Hz at 50% - 50%
  TIGPWM_setFrequency(120, 50);

  // delay for 10 seconds
  delay(10000);

  // generate 1000 Hz at 30% - 70%
  TIGPWM_setFrequency(1000, 30);

  // delay for 10 seconds
  delay(10000);

  // generate 30 Hz at 80% - 20%
  TIGPWM_setFrequency(30, 80);

  // delay for 10 seconds
  delay(10000);

  // generate 333 kHz at 40% - 60%
  TIGPWM_setFrequency(333000, 40);

  // delay for 30 ms
  delay(30);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Changing the frequency and pulse width is as easy as calling the function TIGPWM_setFrequency(freq, dutyCycle)

The PWMs are complimentary, for example, if D9 is 40%, D10 is 60% (as per requirement). You only need to set the pulse width (duty cycle) of D9 and D10 is computed and set automagically (which will only require you a single POT adjustment)

The PWM signals are done in hardware so it doesn't take CPU cycles. You can use delay() and millis() all day and it won't affect the frequency and duty cycles of the PWM signal.

The PWM frequency is code limited to 2 MHz (technically, you can go up to 8 MHz on the UNO/MEGA/MINI with 16 MHz crystal)

aaa.png

aaa.png

tigpwm.c (1.77 KB)

tigpwm.h (175 Bytes)

It’s going to take me a while to figure this out. If I use a PWM signal, can I adjust the overall frequency of the wave and adjust the duty cycle without changing the overall frequency? Also, I understand these MOSFETS are limited to around 500KHZ which is why I chose around 300KHZ for the start pulse. I don’t think duty cycle matters for that but it’s something I will have to experiment with. So far, it looks like my panel will have a POT for HZ, one for the duty cycle, and the LCD. I might could add a POT to play with the start pulse but that will only be monkeyed with until it works right and never again.

Thanks for all the help. I just need to learn more coding so I can figure it out. I’m just figuring out how to set up libraries manually.

I wasn’t able to open these libraries in the Arduino IDE. I was able to open them in a word processor. I’m guessing you did this in straight C++ and used a compiler? I also noticed it looks like you are using direct port manipulation. I appreciate the help, but I’m just learning programming and this is just way above my head. I found a library “avr/io.h” within your library. Is that meant for your compiler? Is there any chance I could get you to just paste the code into one sketch so I can at least handle the file as one piece? Maybe some day I’ll be able to figure out what you have done. For now, I’d like to just be able to figure out what to wire to which pins just to see what happens.

#include <avr/io.h>
#include "tigpwm.h"


void TIGPWM_init(void)
{
  /***************************
  Initialize the PWM hardware
  ***************************/

  // set OC1x output pins 
  DDRB |= 1<<PORTB1 | 1<<PORTB2;

  // set TIMER1 for Fast PWM mode, opposite output on OC1x pins
  TCCR1A = 1<<WGM11 | 0<<WGM10 | 1<<COM1A1 | 1<<COM1A0 | 1<<COM1B1 | 0<<COM1B0;
  TCCR1B = 1<<WGM13 | 1<<WGM12;

  // disable interrupts
  TIMSK1 = 0<<OCIE1B | 0<<OCIE1A | 0<<TOIE1;

  // set initial TOP value to generate 120 Hz [250 KHz / 2084]
  ICR1 = (2084 - 1);

  // set initial duty cycles at 50%
  OCR1A = 1042;
  OCR1B = 1042;

  // start TIMER1 at 250 KHz [DIV64]
  //TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 1<<CS11 | 1<<CS10;
  TCCR1B = 1<<WGM13 | 1<<WGM12;

  return;
}

void TIGPWM_setFrequency(uint32_t freq, uint16_t duty)
{
  uint8_t PRESCALER = 0;
  uint32_t dutyOCxR = 0;
  uint32_t icr1Tmp = 0;

  // stop the TIMER first
  TCCR1B = 0;
  TCNT1 = 0;
  asm("NOP");
  asm("NOP");
  asm("NOP");

  // limit duty cycle to 100%
  if(duty > 100) {
    duty = 100;
  }

  // limit PWM frequency to 2 MHz
  if(freq > 2000000UL) {
    freq = 2000000UL;
  }

  // if desired freq is above 100 KHz
  if(freq > 100000UL) {
    // use DIV1
    PRESCALER = 0<<CS12 | 0<<CS11 | 1<<CS10;
    icr1Tmp = (uint32_t) ((16000000UL/freq) - 1);
  }
  else {
    // used DIV64
    PRESCALER = 0<<CS12 | 1<<CS11 | 1<<CS10;
    icr1Tmp = (uint32_t) ((250000UL/freq) - 1);
  }

  dutyOCxR = (icr1Tmp * duty)/100UL;

  // TOP value to determine period (PWM frequency)
  ICR1 = (uint16_t) icr1Tmp;

  // duty cycles (complimentary on the two output)
  OCR1A = (uint16_t) dutyOCxR;
  OCR1B = (uint16_t) dutyOCxR;

  // start TIMER1 to generate frequency output
  TCCR1B = 1<<WGM13 | 1<<WGM12 | PRESCALER;

  return;
}

Do you know how to do RFI suppression? Because, if not, you will be broadcasting strong radio interference on all the harmonics of your PWM frequency.

found a library “avr/io.h” within your library. Is that meant for your compiler?

It’s for my compiler but the Arduino IDE already includes it so you don’t have to put that in. You can just combine everything in a single sketch and the Arduino IDE does all the magic. The details are dirty, but that applies to any library that you didn’t write.

void setup() {
  
  // setup D9 and D10 as complimentary PWM outputs
  TIGPWM_init();

  // generate 120 Hz at 50% - 50%
  TIGPWM_setFrequency(120, 50);

  // delay for 10 seconds
  delay(10000);

  // generate 1000 Hz at 30% - 70%
  TIGPWM_setFrequency(1000, 30);

  // delay for 10 seconds
  delay(10000);

  // generate 30 Hz at 80% - 20%
  TIGPWM_setFrequency(30, 80);

  // delay for 10 seconds
  delay(10000);

  // generate 333 kHz at 40% - 60%
  TIGPWM_setFrequency(333000, 40);

  // delay for 30 ms
  delay(30);

}



void loop() {
  // put your main code here, to run repeatedly:

}

//********************************************************************************************************
//********************************************************************************************************

void TIGPWM_init(void)
{
  /***************************
  Initialize the PWM hardware
  ***************************/

  // set OC1x output pins
  DDRB |= 1<<PORTB1 | 1<<PORTB2;

  // set TIMER1 for Fast PWM mode, opposite output on OC1x pins
  TCCR1A = 1<<WGM11 | 0<<WGM10 | 1<<COM1A1 | 1<<COM1A0 | 1<<COM1B1 | 0<<COM1B0;
  TCCR1B = 1<<WGM13 | 1<<WGM12;

  // disable interrupts
  TIMSK1 = 0<<OCIE1B | 0<<OCIE1A | 0<<TOIE1;

  // set initial TOP value to generate 120 Hz [250 KHz / 2084]
  ICR1 = (2084 - 1);

  // set initial duty cycles at 50%
  OCR1A = 1042;
  OCR1B = 1042;

  // start TIMER1 at 250 KHz [DIV64]
  //TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 1<<CS11 | 1<<CS10;
  TCCR1B = 1<<WGM13 | 1<<WGM12;

  return;
}

void TIGPWM_setFrequency(uint32_t freq, uint16_t duty)
{
  uint8_t PRESCALER = 0;
  uint32_t dutyOCxR = 0;
  uint32_t icr1Tmp = 0;

  // stop the TIMER first
  TCCR1B = 0;
  TCNT1 = 0;
  asm("NOP");
  asm("NOP");
  asm("NOP");

  // limit duty cycle to 100%
  if(duty > 100) {
    duty = 100;
  }

  // limit PWM frequency to 2 MHz
  if(freq > 2000000UL) {
    freq = 2000000UL;
  }

  // if desired freq is above 100 KHz
  if(freq > 100000UL) {
    // use DIV1
    PRESCALER = 0<<CS12 | 0<<CS11 | 1<<CS10;
    icr1Tmp = (uint32_t) ((16000000UL/freq) - 1);
  }
  else {
    // used DIV64
    PRESCALER = 0<<CS12 | 1<<CS11 | 1<<CS10;
    icr1Tmp = (uint32_t) ((250000UL/freq) - 1);
  }

  dutyOCxR = (icr1Tmp * duty)/100UL;

  // TOP value to determine period (PWM frequency)
  ICR1 = (uint16_t) icr1Tmp;

  // duty cycles (complimentary on the two output)
  OCR1A = (uint16_t) dutyOCxR;
  OCR1B = (uint16_t) dutyOCxR;

  // start TIMER1 to generate frequency output
  TCCR1B = 1<<WGM13 | 1<<WGM12 | PRESCALER;

  return;
}

I wasn't able to open these libraries in the Arduino IDE. I was able to open them in a word processor.

Try out notepad++

Please tell me more about this.

hzrnbgy:
It’s for my compiler but the Arduino IDE already includes it so you don’t have to put that in. You can just combine everything in a single sketch and the Arduino IDE does all the magic. The details are dirty, but that applies to any library that you didn’t write.

void setup() {

// setup D9 and D10 as complimentary PWM outputs
 TIGPWM_init();

// generate 120 Hz at 50% - 50%
 TIGPWM_setFrequency(120, 50);

// delay for 10 seconds
 delay(10000);

// generate 1000 Hz at 30% - 70%
 TIGPWM_setFrequency(1000, 30);

// delay for 10 seconds
 delay(10000);

// generate 30 Hz at 80% - 20%
 TIGPWM_setFrequency(30, 80);

// delay for 10 seconds
 delay(10000);

// generate 333 kHz at 40% - 60%
 TIGPWM_setFrequency(333000, 40);

// delay for 30 ms
 delay(30);

}

void loop() {
 // put your main code here, to run repeatedly:

}

//********************************************************************************************************
//********************************************************************************************************

void TIGPWM_init(void)
{
 /***************************
 Initialize the PWM hardware
 ***************************/

// set OC1x output pins
 DDRB |= 1<<PORTB1 | 1<<PORTB2;

// set TIMER1 for Fast PWM mode, opposite output on OC1x pins
 TCCR1A = 1<<WGM11 | 0<<WGM10 | 1<<COM1A1 | 1<<COM1A0 | 1<<COM1B1 | 0<<COM1B0;
 TCCR1B = 1<<WGM13 | 1<<WGM12;

// disable interrupts
 TIMSK1 = 0<<OCIE1B | 0<<OCIE1A | 0<<TOIE1;

// set initial TOP value to generate 120 Hz [250 KHz / 2084]
 ICR1 = (2084 - 1);

// set initial duty cycles at 50%
 OCR1A = 1042;
 OCR1B = 1042;

// start TIMER1 at 250 KHz [DIV64]
 //TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 1<<CS11 | 1<<CS10;
 TCCR1B = 1<<WGM13 | 1<<WGM12;

return;
}

void TIGPWM_setFrequency(uint32_t freq, uint16_t duty)
{
 uint8_t PRESCALER = 0;
 uint32_t dutyOCxR = 0;
 uint32_t icr1Tmp = 0;

// stop the TIMER first
 TCCR1B = 0;
 TCNT1 = 0;
 asm(“NOP”);
 asm(“NOP”);
 asm(“NOP”);

// limit duty cycle to 100%
 if(duty > 100) {
   duty = 100;
 }

// limit PWM frequency to 2 MHz
 if(freq > 2000000UL) {
   freq = 2000000UL;
 }

// if desired freq is above 100 KHz
 if(freq > 100000UL) {
   // use DIV1
   PRESCALER = 0<<CS12 | 0<<CS11 | 1<<CS10;
   icr1Tmp = (uint32_t) ((16000000UL/freq) - 1);
 }
 else {
   // used DIV64
   PRESCALER = 0<<CS12 | 1<<CS11 | 1<<CS10;
   icr1Tmp = (uint32_t) ((250000UL/freq) - 1);
 }

dutyOCxR = (icr1Tmp * duty)/100UL;

// TOP value to determine period (PWM frequency)
 ICR1 = (uint16_t) icr1Tmp;

// duty cycles (complimentary on the two output)
 OCR1A = (uint16_t) dutyOCxR;
 OCR1B = (uint16_t) dutyOCxR;

// start TIMER1 to generate frequency output
 TCCR1B = 1<<WGM13 | 1<<WGM12 | PRESCALER;

return;
}

You are clearly a very advanced coder. I’d love to be able to have a close look at your work. It would really help my skills improve as well as I am sure, others who will find this thread. Would you be willing to translate this into standard code and put it all on one page? I just don’t have the experience at this time to look at port manipulation and pick up on the logic. Unless, you want to explain what all that means.
I think a lot of people could benefit from your experience if not overwhelmed. And this would be a fantastic utility for a lot of DIY fabricators who don’t have a couple grand for a TIG welder. I sure would appreciate it, as would many others I would think.

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