', { cookie_domain: 'auto', cookie_flags: 'max-age=0;domain=.tistory.com', cookie_expires: 7 * 24 * 60 * 60 // 7 days, in seconds }); 'Stopped/슈퍼 캐패시터 스폿 용접기' 카테고리의 글 목록 :: MakerLee's Workspace
728x90

마무리만 하면 되는 상황에서 고민을 많이 했습니다만

중단하기로 했습니다. 

캐패시터 스폿 자체에는 전혀 문제가 없습니다. 

문제는 제가 계획중인 프로젝트 중에

스텐레스 박판이나 강철 와이어의 스폿용접이 필요할 수도 있다는거죠. 

캐패시터 스폿은 순간적으로 빠른 전압 강하가 일어나기 때문인지

다른 용도의 스폿에는 사용하기가 힘들더군요.

2번이나 제작한 캐패시터 PCB 뭉치를 포기하려니 아까운 마음에 고민을 했습니다만

과감하게 중단하고 다시 AC 스폿기로 돌아가야 할 것 같습니다. 

 


#include <EEPROM.h>
#include <Encoder.h> // https://github.com/PaulStoffregen/Encoder
#include <U8glib.h>


U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);


//이하 핀 선언
#define encoderA 2			//엔코더 A상 - interrupt of arduino nano
#define encoderB 3			//엔코더 B상 - interrupt of arduino nano
#define encoderSW 4			//엔코더스위치
#define spotSignal 5		//스폿 출력	
#define piezo 6 			//피에조 출력
#define spotSW 7			//스폿 트리거 스위치 
#define FanControl 13		//팬 출력. pwm체크할것. 
#define VoltagePin A0		//전압체크 입력
#define tempPin A1			//온도센서 입력
#define autoSpotCheckPin A2	//오토스폿 체크 입력

//이하 음계 주파수 선언
#define B7  3951
#define C8  4186 

//이하 변수 선언
float voltage;					//전압
boolean manualMode = true;		// 수동/자동 모드 선택
boolean dualMode = false;		//듀얼모드 선택
float spotTime= 0.1;			// 스폿 시간
boolean spotFlag = false;		//스폿이 실행됐는지 아닌지 저장하는 플래그. 
double intervalTime = 1.5;		//오토모드시 인터벌 타임 
float dualTime = 0.5;			//듀얼모드시 듀얼 타임
unsigned long currentTime;		//인터벌 시간을 측정하기 위해 millis()를 저장하는 변수 
unsigned long previousTime;		//인터벌 시간을 측정하기 위해 millis()를 저장하는 변수 
char voltageChar[4];				
char temperatureChar[4];
char spotTimeChar[4];
char intervalTimeChar[4];
char dualTimeChar[4];

//EEPROM 관련 변수 선언
int spotTimeAddress = 0;
int autoTimeAddress = 10;


int menuSelect = 0;				//화면에서 선택된 메뉴를 구분하는 변수. 0=수폿시간, 1=자동/수동 선택 2=인터벌, 3=듀얼모드, 4=듀얼시간, 


//온도관련 변수 선언
#define thermistorR 10000				//써미스터 저항값
#define Coefficient 3950		//써미스터 계수
#define tempNorm 25			//보통 실온의 온도 
#define resistorR 10000			//병렬저항의 저항값
#define numSamples 3			//평균을 몇 번 낼 것인가
uint16_t samples[numSamples];
float temperature, average;	//온도, 평균온도

//엔코더 관련 플래그 변수 선언
boolean encoderFlagUp;          //엔코더에서 들어온 UP 신호 플래그(UP 행동후 false 전환)
boolean encoderFlagDown;        //엔코더에서 들어온 DOWN 신호 플래그(DOWN 행동후 false전환)
boolean SWpressedFlag = false;        //스위치가 눌렸는지 저장하는 플래그 변수 
int oldPosition  = 0;

Encoder myEncoder(encoderA, encoderB);


const uint8_t PROGMEM boot[]  = {
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x78,0x03,0xfe,0x00,
	0x00,0x7f,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0x80,0x7c,0x03,0xff,0x00,
	0x00,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x80,0xfc,0x03,0xff,0x80,
	0x00,0xf0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x81,0x80,0xfc,0x03,0xc3,0x80,
	0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0xfe,0x03,0xc3,0xc0,
	0x00,0xe0,0x03,0x83,0x87,0x7c,0x01,0xf0,0x3b,0x9e,0x00,0x01,0xee,0x03,0xc3,0xc0,
	0x00,0xf0,0x03,0x83,0x87,0xfe,0x07,0xf8,0x3f,0x9c,0x00,0x01,0xcf,0x03,0xc3,0xc0,
	0x00,0x7c,0x03,0x83,0x87,0xff,0x0f,0xfc,0x3f,0x9c,0x00,0x03,0xcf,0x03,0xc7,0x80,
	0x00,0x3e,0x03,0x83,0x87,0x8f,0x0f,0x1c,0x3c,0x3c,0x00,0x03,0xc7,0x03,0xff,0x80,
	0x00,0x1f,0x83,0x83,0x87,0x87,0x9e,0x1e,0x3c,0x3c,0x00,0x07,0x87,0x83,0xff,0x00,
	0x00,0x07,0xc3,0x83,0x87,0x07,0x9f,0xfe,0x38,0x1c,0x00,0x07,0x83,0x83,0xfc,0x00,
	0x00,0x03,0xc3,0x83,0x87,0x03,0x9f,0xfe,0x38,0x1c,0x00,0x07,0xff,0xc3,0xc0,0x00,
	0x00,0x01,0xe3,0x83,0x87,0x03,0x9f,0xfe,0x38,0x1e,0x00,0x0f,0xff,0xc3,0xc0,0x00,
	0x00,0x01,0xe3,0x83,0x87,0x07,0x9e,0x00,0x38,0x0f,0x00,0x0f,0xff,0xe3,0xc0,0x00,
	0x00,0x83,0xc3,0xc7,0x87,0x07,0x8f,0x0c,0x38,0x0f,0xc1,0x1e,0x01,0xe3,0xc0,0x00,
	0x00,0xff,0xc3,0xff,0x87,0x8f,0x0f,0xfc,0x38,0x07,0xff,0x9e,0x00,0xe3,0xc0,0x00,
	0x00,0xff,0x81,0xff,0x87,0xff,0x07,0xfc,0x38,0x03,0xff,0xbc,0x00,0xf3,0xc0,0x00,
	0x00,0x7e,0x00,0xfb,0x87,0xfe,0x01,0xf8,0x38,0x00,0x7e,0x3c,0x00,0x73,0xc0,0x00,
	0x00,0x00,0x00,0x00,0x07,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x0f,0xf0,0x00,0x00,0x07,0x80,0x00,0x07,0x80,
	0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x7f,0xfc,0x01,0xff,0x87,0x80,0x00,0x07,0x80,
	0x00,0x03,0x80,0x00,0xff,0xff,0x00,0xff,0xfe,0x01,0xff,0x87,0x83,0xff,0xc7,0x80,
	0x00,0x03,0x80,0x00,0x3c,0x38,0x00,0xf0,0x1f,0x01,0xff,0x87,0x83,0xff,0xc7,0x80,
	0x00,0x07,0x80,0x00,0x3c,0x38,0x00,0xe0,0x0f,0x00,0x07,0x87,0x81,0xff,0xc7,0x80,
	0x00,0x07,0xc0,0x00,0x3c,0x38,0x00,0xf0,0x1f,0x00,0x0f,0x7f,0x80,0x03,0xc7,0x80,
	0x00,0x0f,0xe0,0x01,0xff,0xff,0x00,0xff,0xfe,0x00,0x1f,0x7f,0x80,0x03,0xc7,0x80,
	0x00,0x0f,0xe0,0x01,0xff,0xff,0x00,0x7f,0xfc,0x00,0x1e,0x7f,0x80,0x03,0x87,0x80,
	0x00,0x1e,0xf0,0x01,0xff,0xff,0x00,0x3f,0xf8,0x00,0x7f,0x07,0x80,0x03,0x87,0x80,
	0x00,0x7e,0x7c,0x00,0x03,0x80,0x00,0x38,0x38,0x00,0xff,0xc7,0x80,0x07,0x87,0x80,
	0x01,0xfc,0x3f,0x00,0x03,0x80,0x00,0x38,0x38,0x01,0xfb,0xf7,0x80,0x0f,0x07,0x80,
	0x03,0xf0,0x1f,0x8f,0xff,0xff,0xef,0xff,0xff,0xe7,0xe1,0xe7,0x80,0x0f,0x07,0x80,
	0x03,0xe0,0x0f,0x8f,0xff,0xff,0xef,0xff,0xff,0xe3,0xc0,0x47,0x80,0x1e,0x07,0x80,
	0x01,0x80,0x03,0x0f,0xff,0xff,0xef,0xff,0xff,0xe3,0x00,0x00,0x00,0x3c,0x07,0x80,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x07,0x80,0xf8,0x07,0x80,
	0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x0f,0xf0,0x00,0x38,0x07,0x81,0xf0,0x07,0x80,
	0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x7f,0xfc,0x00,0x3f,0xff,0x87,0xe0,0x07,0x80,
	0x0f,0xff,0xff,0xe0,0x07,0xc0,0x00,0xff,0xfe,0x00,0x3f,0xff,0x83,0xc0,0x07,0x80,
	0x0f,0xff,0xff,0xe0,0x07,0xc0,0x00,0xf0,0x1f,0x00,0x3f,0xff,0x81,0x80,0x07,0x80,
	0x0f,0xff,0xff,0xe0,0x1f,0xf0,0x00,0xe0,0x0f,0x00,0x38,0x07,0x80,0x00,0x07,0x80,
	0x00,0x00,0x00,0x00,0x7e,0x7e,0x00,0xf0,0x1f,0x00,0x38,0x07,0x80,0x00,0x07,0x80,
	0x00,0x00,0x00,0x03,0xf8,0x3f,0x80,0xff,0xfe,0x00,0x3f,0xff,0x80,0x00,0x07,0x80,
	0x00,0x00,0x00,0x01,0xf0,0x1f,0x80,0x7f,0xfc,0x00,0x3f,0xff,0x80,0x00,0x07,0x80,
	0x00,0x00,0x00,0x01,0x80,0x03,0x00,0x0f,0xf0,0x00,0x3f,0xff,0x00,0x00,0x07,0x80,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

//수동 
const unsigned char PROGMEM manual[] = {
	0x00,0x00,0x00,
	0x00,0x0e,0x00,
	0x00,0x0e,0x00,
	0x00,0x0e,0x00,
	0x00,0x1e,0x00,
	0x00,0x3f,0x80,
	0x00,0xf3,0xe0,
	0x07,0xe0,0xf0,
	0x07,0x80,0x30,
	0x00,0x00,0x00,
	0x00,0x00,0x00,
	0x1f,0xff,0xfc,
	0x1f,0xff,0xfc,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x00,0x00,0x00,
	0x00,0x00,0x00,
	0x03,0xff,0xe0,
	0x03,0xff,0xe0,
	0x01,0x80,0x00,
	0x01,0x80,0x00,
	0x01,0xff,0xe0,
	0x01,0xff,0xe0,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x1f,0xff,0xfc,
	0x1f,0xff,0xfc,
	0x00,0x00,0x00,
	0x00,0x00,0x00,
	0x00,0x7f,0x80,
	0x00,0xff,0xc0,
	0x01,0xc0,0xe0,
	0x01,0x80,0x60,
	0x01,0xc0,0xe0,
	0x00,0xff,0xc0,
	0x00,0x7f,0x80
}; 

//자동
const unsigned char PROGMEM	automatic[] = {
	0x00,0x00,0xe0,
	0x00,0x00,0xe0,
	0x00,0x00,0x60,
	0x0f,0xfc,0x60,
	0x0f,0xfc,0x60,
	0x00,0x18,0x60,
	0x00,0x38,0x60,
	0x00,0x30,0x60,
	0x00,0x70,0x60,
	0x00,0xf0,0x7e,
	0x01,0xf8,0x7e,
	0x03,0x9c,0x60,
	0x07,0x0e,0x60,
	0x1e,0x07,0x60,
	0x1c,0x03,0x60,
	0x00,0x00,0x60,
	0x00,0x00,0x60,
	0x00,0x00,0x60,
	0x00,0x00,0x60,
	0x00,0x00,0x60,
	0x00,0x00,0x00,
	0x00,0x00,0x00,
	0x03,0xff,0xe0,
	0x03,0xff,0xe0,
	0x01,0x80,0x00,
	0x01,0x80,0x00,
	0x01,0xff,0xe0,
	0x01,0xff,0xe0,
	0x00,0x0c,0x00,
	0x00,0x0c,0x00,
	0x1f,0xff,0xfc,
	0x1f,0xff,0xfc,
	0x00,0x00,0x00,
	0x00,0x00,0x00,
	0x00,0x7f,0x80,
	0x00,0xff,0xc0,
	0x01,0xc0,0xe0,
	0x01,0x80,0x60,
	0x01,0xc0,0xe0,
	0x00,0xff,0xc0,
	0x00,0x7f,0x80
};



void u8g_prepare() {
  u8g.setFont(u8g_font_7x13B);		//
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop();
}


void setup() {
	pinMode(encoderSW, INPUT);
	pinMode(encoderA, INPUT);
	pinMode(encoderB, INPUT);
	pinMode(spotSignal, OUTPUT);
	pinMode(piezo, OUTPUT);
	pinMode(spotSW, INPUT_PULLUP);
	pinMode(autoSpotCheckPin, INPUT);
	pinMode(FanControl, OUTPUT);
	pinMode(VoltagePin, INPUT);
	pinMode(tempPin, INPUT);

	u8g_prepare();


    u8g.firstPage();  //두번째 로고를 그린다.
      do {
      	// drawBitmapP(X,Y,Count,H) 에서 count는 비트맵의 가로픽셀수/8, H는 세로픽셀수 이다. 
        u8g.drawBitmapP( 0, 0, 16, 64, boot);	
      }
      while(  u8g.nextPage() ) ;  
	delay(100);

	previousTime = millis();

	beepbeep();
	//Serial.begin(9600);


	//spotTime = EEPROM.read(spotTimeAddress);
	//autoTime = EEPROM.read(autoTimeAddress);
}

void loop() {

	//전압 체크
	voltage = analogRead(VoltagePin);
	voltage = voltage *(5.0/1024.0)*5.3;  //입력 아날로그값(1024)를 5V 수치로 변환시킨 후 전압분배 저항값만큼(5.3)곱한다

	//온도 체크
	for (int i = 0; i<numSamples; i++){
		samples[i] = analogRead(tempPin);
	}

	average = 0;

	for (int i = 0; i<numSamples; i++){
		average += samples[i];
	}

	average /= numSamples;
	average = 1023 / average - 1;
	average = resistorR / average;

	temperature = average / thermistorR;  // (R/Ro)
	temperature = log(temperature);					//ln(R/Ro)
	temperature /= Coefficient;				//1/B * ln(R/Ro)
	temperature += 1.0 / (tempNorm + 273.15);	// + (1/To)
	temperature = 1.0 / temperature;				// Invert
	temperature -= 273.15;					// convert to C

	//소수점 이하 자리를 2 단위로 끊기 위한 계산처리
	temperature *= 5;
	temperature = round(temperature);
	temperature /= 5; 		

	//이하 엔코더 입력 처리
	    if(digitalRead(encoderSW)==HIGH){       //스위치가 눌리면 일단 기억한다. 
	    	SWpressedFlag = true;
	    }

	    if(digitalRead(encoderSW)==LOW && SWpressedFlag==true){  //스위치가 안 눌리면, 눌렸는지 확인하고 그렇다면 아래 구문을 실행
			menuSelect++;								//스위치가 눌리면 스폿시간, 자동/수동 선택, 인터벌 시간 등을 돌아가며 선택한다
			if((menuSelect==4)&&(dualMode==false)){
				menuSelect = 0;
			}
			if(menuSelect>4){
				menuSelect = 0;
			}
			beep();
			SWpressedFlag = false;
	    }

    readEncoder();
    if(encoderFlagUp==true){ 		//상승 트리거 선택시
    	switch (menuSelect) {
    	    case 0:		//0=스폿시간, 3=듀얼모드, 4=듀얼시간, 
    	    	if(spotTime<10){
    	    		spotTime= spotTime+0.5;
    	    	}
    	    	else{
    	    		spotTime++;
    	    	}
    	    break;

    	    case 1:		//1=자동/수동 선택
    	    	manualMode =! manualMode;
    	    break;

    	    case 2:		//2=인터벌 시간 조정
    	    	intervalTime = intervalTime+0.1;
    	    	if(intervalTime>5){		//인터벌 시간이 5초를 넘지 않도록 설정. 
    	    		intervalTime = 5;
    	    	}
    	    break;

    	    case 3:		//3=듀얼/싱글모드 선택
    	    	dualMode =! dualMode;
    	    break;

    	    case 4:		//4=듀얼일 경우 시간 조정
    	    	if(dualMode==true){
		    		dualTime = dualTime + 0.5;
		    	}
    	}
    	beep();
    	encoderFlagUp = false;
    }

    if(encoderFlagDown==true){		//하강 트리거 선택시
    	switch (menuSelect) {
		    case 0:		//0=스폿시간
		    	if(spotTime<10){
		    		spotTime= spotTime - 0.5;
		    	}
		    	else{
		    		spotTime--;
		    	}
		    break;

		    case 1:		//1=자동/수동 선택
		    	manualMode =! manualMode;
		    break;

		    case 2:		//2=인터벌 시간 조정
		    	intervalTime = intervalTime - 0.1;
		    	if(intervalTime<0.5){		//인터벌 시간이 0.5초 이하가 되지 않도록 설정. 
		    		intervalTime = 0.5;
		    	}
		    break;

		    case 3:		//3=듀얼/싱글모드 선택
		    	dualMode =! dualMode;
		    break;

		    case 4:		//듀얼일 경우 듀얼 시간 조정
		    	if(dualMode==true){
		    		dualTime = dualTime - 0.5;
		    	}
			}
		encoderFlagDown = false;
    	beep();
    }

    if(spotTime<0.5){			//스폿 시간이 0이 되지 않도록 처리
    	beepbeep();
    	spotTime = 0.5;
    }
    if(manualMode == true){		//수동 모드일 때
	    if((digitalRead(spotSW)==LOW) && (spotFlag==false)){		//스폿 스위치가 눌리면 스폿한다.
	    	currentTime = millis();
	    	if(currentTime > (previousTime + (intervalTime*1000))){
	    		spot();
	    	}
	    }
	    if(digitalRead(spotSW)==HIGH){
	    	spotFlag = false;
	    }
	}
	else if((analogRead(autoSpotCheckPin)>400) && (spotFlag==false)){	//자동 모드일 때 A2핀에 2/5 이상의 전압이 걸리면
		delay(intervalTime*1000);   									//인터벌 시간 후 스폿 
		currentTime = millis();
	    	if(currentTime > (previousTime + (intervalTime*1000))){
	    		spot();
	    	}
	    }
	    if(digitalRead(spotSW)==HIGH){
	    	spotFlag = false;
	    }
	

    draw();  //OLED 그리는 함수 호출 

}






void readEncoder(){   //엔코더를 오른쪽으로 돌리는 것을 UP으로 설정한다. 
  int newPosition = myEncoder.read();

  if ((newPosition+1) < oldPosition) {      //값의 변화가 생기면 오른 값인지 내린 값인지 비교하여 Flag 설정. 
    encoderFlagUp = true;                   // +1 과 -1을 해주는 이유는 분해능 때문에 3번씩 반복되는것을 막기 위함  
  }
  if ((newPosition-1) > oldPosition) {
    encoderFlagDown = true;   
  }
	oldPosition = newPosition;
  	if(oldPosition > 32760 || oldPosition < -32760){
   	oldPosition = 0;        //int 변수의 범위를 벗어나지 않도록 고정. 
  }
}

void draw(){

	u8g.firstPage();  //화면에 기본 정보 표시 
	do {

		//수동/자동 글자 표시
		if(manualMode == true){		//수동일 경우-수동 선택 표시 
		u8g.drawBitmapP( 0, 20, 3, 41, manual);
		}
		else{							//자동일 경우	
		u8g.drawBitmapP( 0, 20, 3, 41, automatic);
		}

    	//구분선 표시
		u8g.drawLine(0, 0, 128, 0);
		u8g.drawLine(0, 14, 128, 14);
		
		//전압표시
		dtostrf(voltage,2,1,voltageChar);	
		u8g.drawStr(5,2,voltageChar);
		if(voltage<10){
			u8g.drawStr(30,2,"V");
		}
		else{
			u8g.drawStr(38,2,"V");
		}		

		//온도표시
		dtostrf(temperature,2,1,temperatureChar);	
		u8g.drawStr(73,2,temperatureChar);
		u8g.drawStr(103,2,"'C");

		//스폿시간 표시 
		u8g.setScale2x2();			
		if(spotTime<10){			//스폿시간이 10보다 작으면 위치를 조정
			dtostrf(spotTime,2,1,spotTimeChar);
			u8g.drawStr(23, 19, spotTimeChar);
			u8g.drawStr(45, 19, "ms");
		}
		else{						//10보다 크면 위치를 조정. 
			dtostrf(spotTime,2,0,spotTimeChar);
			u8g.drawStr(27, 19, spotTimeChar);
			u8g.drawStr(43, 19, "ms");
		}
		u8g.undoScale();

		//인터벌 시간 표시
		u8g.drawStr(32, 21, "I");
		dtostrf(intervalTime, 2, 1, intervalTimeChar);
		u8g.drawStr(43, 21, intervalTimeChar);
		u8g.drawStr(65, 21, "s");

		//듀얼시간 표시 
		if(dualMode == true){
			u8g.drawStr(80, 21, "D");
		}
		else{
			u8g.drawStr(80, 21, "S");
		}
		dtostrf(dualTime, 2, 1, dualTimeChar);
		u8g.drawStr(91,21, dualTimeChar);
		u8g.drawStr(113, 21, "ms");

		//선택된 부분에 사각형 표시
		switch (menuSelect) {		//0=스폿시간, //1=자동/수동 선택 2=인터벌, 3=듀얼모드, 4=듀얼시간, 
		    case 0:
		    	u8g.drawRFrame(35, 35, 92, 29, 4);		//스폿시간
		    break;

		    case 1:
		    	u8g.drawRFrame(0, 18, 25, 46, 3);		//수동/자동
		    break;
		    
		    case 2:
		    	u8g.drawRFrame(28, 18, 47, 17, 3);		//인터벌
		    break;
		    
		    case 3:
		    	u8g.drawRFrame(76, 18, 13, 17, 2);		//듀얼모드/싱글모드
		    break;
		    
		    case 4:
		    	u8g.drawRFrame(88, 18, 40, 17, 3);		//듀얼일 경우 듀얼 시간 
		    break;
		}

		//u8g.drawRFrame(20, 40, 20, 20, 3);  //시작점(왼쪽 위)의 X좌표, Y좌표, 박스의 폭, 박스의 높이, R값
	}
	while(  u8g.nextPage() ) ;   
}

void spot(){
	spotFlag = true;
	digitalWrite(spotSignal, HIGH);
	delayMicroseconds(spotTime*1000);
	digitalWrite(spotSignal, LOW);
	if(dualMode==true){
		delayMicroseconds(dualTime*1000);
		digitalWrite(spotSignal, HIGH);
		delayMicroseconds(spotTime*1000);
		digitalWrite(spotSignal, LOW);		
		beep();
	}
	beep();
	previousTime = currentTime;
}

void beepbeep(){
  tone(piezo, B7, 50);
  delay(100);
  tone(piezo, B7, 50);
  delay(100);
}

void beep(){
  tone(piezo, C8, 30);
  delay(40);
}

728x90
728x90

 

PCB를 조립하고 테스트 스폿을 했을 때 니켈판이 전혀 붙지가 않더군요

 

 

 

 

 

 

 

전압을 높이고 별짓을 다해도 붙질 않았습니다. 

커터칼 없이 니켈판만 대고 해보면 구멍을 뻥뻥 뚫을 정도로 강력한데 이상하더군요.

 

 

 

 

 

 

 

 

 

전부 분해해서 접점을 깨끗하게 연마했습니다. 

 

 

 

 

 

반짝반짝 광나게 닦았습니다. 

스폿 용접기는 저전압 고전류를 사용하는지라 작은 저항의 차이도 큰 변화를 가져옵니다. 

 

 

 

 

 

 

 

동 부스바는 표면산화가 빨라서 금방 원래대로 될 것 같더군요.

프로젝트 원저자가 사용하던 Noalox라는 접점용 산화 차단제를 발라봤습니다. 

근데 이 용액 자체는 전도도가 0이던데 접점에 사용해도 전기 전도에 영향이 없는지 모르겠네요

 

 

 

 

 

 

잘 연마하고 잘 조립했더니 체감상 성능이 좋아졌습니다만 결과는 마찬가지로 잘 안붙더군요.

니켈도금판이 아닌 순수 니켈판으로 해봤더니 아주 잘됩니다. 

검색해보니 커터칼에는 워낙 잘 안붙는 경우가 있답니다.

니켈도금판과 커터칼 조합은 잘 안되는것 같습니다. 

 

 

 

 

 

 

 

어쨋건 성능문제는 해결했습니다.

길쭉한 부스바를 잘라내고 용접봉이 전면을 향하게 90도 절곡을 하기로 했습니다. 

 

 

 

 

 

 

생각보다 꺾는게 굉장히 힘들더군요.

일반 펜치 정도로는 절대 불가능합니다. 

바이스와 바이스 클램프를 사용해서 간신히 45도 정도 꺾고 바이스에 물린채로 망치질해서 90도 만들어줬습니다. 

표면이 울퉁불퉁해져서 다시 사포질로 매끈하게 정리했습니다. 

 

 

 

 

 

 

테스트해보니 수정하고 싶은 부분이 좀 생겼습니다. 

아두이노의 전원을 따로 만들어 2원화 하거나 전원보강을 해 줘야 할 것 같습니다. 

스폿후 캐패시터 충전하느라 전류가 딸려 OLED 화면이 깜박깜박 합니다. 

캐패시터 충전시 순간 요구하는 전류랑이 상당해 어댑터가 리셋될 가능성이 높습니다. 

CC-CV 모듈을 사용해 전류를 제한해야 하지 않을까 싶네요. 

오토스팟 기능도 확인해 봐야 할 것 같습니다. 

이제 슬슬 외형 설계를 들어갈 차례네요. 

728x90
728x90

왜 보통 흔히 그런 말 하지 않나요?

물건을 찾다 찾다 못찾아서 새로 사면 그때 나온다고.

 

 

 

 

 

 

 

 

 

 

 

저는 찾다 찾다 못찾아서 새로 만들었더니 다음날 나왔습니다.  

어처구니가 없네요

 

 

 

 

 

 

 

전부 떼서 새 PCB로 옮겼습니다. 

납을 하도 먹여서 떼는것도 힘드네요.

 

 

 

 

 

 

이글캐드에서 Fusion360으로 바로 3D 모델링을 작성하는 기능이 있습니다. 

물론 부품 라이브러리에 3D Package가 같이 있어야 합니다. 

일단 캐패시터 3D Package만 작성해서 임포트 해봤더니 저렇게 나오는군요. 

FET가 허공에 떠있긴 하지만 나름 괜찮은 것 같습니다. 

나중에 케이스 만들 때 유용할 것 같네요.

 

 

 

 

 

 

핀 간격을 조절해서 앵글 핀헤더끼리 바로 끼워지도록 만들어 봤습니다. 

728x90
728x90

메이커 페어가 끝난 이후 11월 초부터 스폿 용접기를 완성하려고 했습니다. 

그런데

저 캐패시터 PCB 덩어리가 보이질 않더군요. 

10개 묶음이라 대체 어디 구석에 짱박혀 보이지 않을 부피가 아닌데 말이죠.

찾다보면 어디선가 나오겠지.. 하면서 생각나면 여기저기 뒤져보길 반복했습니다.

그런데 안나와요. 

설마 이번엔 찾겠지 하면서 뒤엎길 여러번... 

그런데 안나와요.

거진 6개월을 기다렸습니다.

그런데 정말 안나오네요...

 

 

 

 

 

 

결국 같은 부품을 재주문했습니다.

 

 

 

 

 

 

이참에 PCB도 약간 수정했습니다. 

캐패시터 다리의 솔더면을 최대한 넓게 수정해서 저항을 줄이고

PCB끼리 연결되는 점퍼의 간격을 조절해서 앵글 핀헤더 사용시 그냥 옆으로 끼워서 연결되도록 했습니다.

 

별로 의욕이 안 생기는 작업이지만 그래도 이번엔 완성까지 쭉 달려보도록 해야겠습니다. 

728x90
728x90

아두이노 스케치에서 제일 시간이 오래 걸린건 UI 정렬이었습니다.

화면 완성하다 보니 처음 고른 폰트가 맞지 않았고 다시 정렬해보니 두번째 폰트도 맞지 않았고요. 

결국 세번째 폰트를 고르고 다시 이것저것 정렬해보면서 1픽셀씩 계속 옮겨가며 확인했습니다

 

일단 기능은 

1. ms 단위 스폿

2. 안전을 위해 스위치를 연속으로 눌러도 interval 시간이 지나지 않으면 작동하지 않음

3. 수동으로 스위치를 누르지 않고 전극봉을 접촉하면 스폿되는 자동 스폿 기능(미구현)

4. 매우 짧은 시간 동안 2번 스폿하여 용접이 잘 되도록 하는 듀얼 스폿 기능

5. 온도 모니터링

6. 전압 모니터링

7. 온도에 따른 냉각팬 가변속도(미구현)

입니다. 

 

 

회로는 락시꾼님이 제작한 회로

https://blog.naver.com/kikch/221435954972 를 기본으로 참조해서 이글캐드로 그렸고 

제 사용목적에 맞도록 일부 수정했습니다. 

아두이노 스케치는 전부 제가 따로 작성했고요. 

 

 

 

듀얼스폿 시에는 위처럼 신호가 두번 튑니다. 

그런데 딱히 효용이 있는지는 모르겠네요. 

 

 

 

 

 

 

캐패시터 보드가 총 10개 있는데 4개만 연결해서 테스트중입니다. 

사용된 캐패시터는 내압이 25V입니다. 

일단 5V만 충전해서는 전혀 스폿용접이 안되는군요. 

7V 이상부터 어느정도 유의미하게 용접이 됩니다만 전압이 높다보니 약간씩 불꽃이 튑니다. 

12V는 매우 용접이 잘 됩니다만 불꽃쇼가 펼쳐집니다. 

9V 정도로 절충하면 적당할 것 같습니다. 

캐패시터 보드를 10개 모두 연결하면 5V 에서도 괜찮을수도 있겠습니다. 

 

일단 스폿은 이상없이 잘 되는것을 확인했습니다. 

 

 

 

 

 

 

전압을 높인 상태에서 캐패시터 보드를 줄이면 어떨까 싶어 테스트해봤습니다. 

3개부터는 성능이 떨어지고 2개부터는 거의 스폿이 안됩니다. 

 

 

 

728x90
728x90

지난번에 주문한 PCB는 설계 오류가 있었습니다.

터미널 위치와 작동 스위치 등이 상당히 비 인체공학적이더군요. 

그래도 아예 새로 할 생각까지는 없었는데 구글링하다가 마음에 드는 프로젝트를 발견했습니다. 

 

 

 

출처 : http://www.zeva.com.au/Projects/SpotWelderV2/

 

알루미늄 12mm 각재로 부스바를 가공해서 사용하더군요

뒤쪽의 NOALOX 라는 제품은 전자회로용 알루미늄 컴파운드제입니다.  

아마도 PCB 에 그대로 연결하면 갈바닉 부식 등이 일어날 수 있으니 코팅용으로 사용하는게 아닐까 싶습니다. 

 

 

 

 

이와 같이 연장이 편리하고 접점이 확실합니다. 

또 부품 손상시 유지보수도 편리하겠더군요. 

상단의 3핀 커넥터를 연결시켜 병렬로 쭉 연결하면 신호선이 계속 연장됩니다. 

모듈화가 되어 있어 신호선 컨트롤을 555타이머를 이용하던 아두이노를 이용하던 상관없이 사용 가능하고요.

 

정말 아이디어가 좋고 제가 원하던 것이라 이대로 재 제작하기로 마음먹었습니다. 

 

 

 

원작자가 사용한 47000uF 캐패시터는 너무 비싸서 타오바오에서 비슷한 용량을 골랐습니다. 

성능이 좀 떨어지면 병렬로 늘리면 되지 않을까 합니다. 

 

 

 

 

 

 

MOSFET도 같이 구매했습니다. 

 

 

 

 

 

 

 

받아보니 원작자의 캐패시터와는 사이즈가 달라 라이브러리를 수정하고 주문한 PCB입니다. 

 

 

 

 

 

 

 

잘 맞는군요.. 

어서 조립해서 테스트해봐야겠습니다. 

728x90
728x90

https://blog.naver.com/kikch/221435954972 에서 참조한 회로로 만들었습니다. 

 

슈퍼 캐패시터를 사용하도록 참조해서 수정했고요. 

100% 맘에 들진 않는데 이 사이즈의 기판은 주문할때마다 가격이 꽤나 비쌉니다.
이미 한번 수정한지라 그냥 쓰려고 합니다. 

 

 

 

 

 

 

 

코드는 비교적 간단한 편입니다. 

소스가 공개되어 있지만 참조만 하려고 프린팅했습니다. 

 

 

 

 

 

 

 

1.3" OLED를 사용할 계획인데 가방에 넣어다니다 보면  깨지는 경우가 있어 임시로 보호대를 만들어줬습니다. 

요즘 약한 번아웃 상태라 진행이 좀 느리네요

728x90
728x90

배터리 자작하시는 분들은 스폿 용접기 많이들 자작해 쓰시더군요.

저도 예전에 간단하게 만들어 본 적이 있긴 한데 당시엔 쓸 일이 없었습니다. 

그리고 대충 한번 만들어 본 것이라 여기저기 많이 어설펐죠.

언젠가 제대로 만들어 두는게 좋을 것 같아 분해해서 부품만 챙겨두었습니다. 

그리고는 잊은채로 한참 지났네요. 







스폿 용접기가 정말 쓸일이 많지는 않은데 필요한 일이 생기면 엄청 아쉽습니다. 

최근에는 집에서 쓰는 진공 청소기의 배터리 수명이 다 되어 또 생각이 나더군요.









파워 소스는 여러가지가 있지만 최종적으로는 고전류의 DC 전기가 필요합니다. 

AC 트랜스를 사용하는 방법은 저같이 몇년에 한번 필요한 사람에게는 좀 문제가 있습니다. 

덩치도 크고 무거운 물건을 몇년에 하루이틀 쓰자고 계속 보관하기는 어렵습니다. 

DC 파워를 쓰는 경우 RC용 고방전 리튬 폴리머 배터리를 사용하기도 합니다. 

이경우 리튬폴리머 가격이 비싸고 마찬가지로 몇년에 한두번 쓰자고 비싼 배터리 수명 낭비해가며 구매하기 애매합니다. 

그러던 와중에 '김원규의 만물상' 사이트에서 슈퍼 캐패시터를 저렴하게 팔길래 구매해뒀습니다. 








타오바오에서 사진만 보고 구매했더니 생각보다 너무 큰 용접봉이 왔군요.

가느다란 것보다는 차라리 이게 낫긴 합니다. 









며칠간 스타벅스에서 커피와 함께 작업했습니다. 

전에 만들었던 555타이머 컨트롤러는 발열과 전류 문제가 있는 듯 하여 도선넓이를 여유있게 잡았습니다. 

저걸로도 부족하고 FET에는 추가로 부스바를 달아서 용접할 예정입니다. 

캐패시터는 8직렬이라 좀 과해 보이긴 합니다. 

만충시 20V가 넘어버리게 되죠. 

테스트삼아 납땜해서 전압 측정을 해봤더니 전압이 높아질수록 충전속도가 극악하게 낮아집니다. 

그래서 전압을 좀 여유있게 두고 충전을 적당한 레벨에서 멈추면서 쓰는게 편할 것 같습니다. 

일단 여기까지 해 두고 회로 제작은 CNC 정비가 끝나는 대로 할 예정입니다. 







제어의 핵심은 IRFP3703을 사용한 스위칭 회로입니다. 

컨트롤러로 아주 짧은 시간(0.5ms~1.5ms 전후) 동안 ON/OFF를 해서 100A 도 넘는 고전류를 흘려줍니다. 

그러면 접촉면이 녹게 되고 그때 용접이 되는 원리입니다. 

실제로는 0.몇초 사이에 용접이 되므로 사람이 느끼기에는 뜨거워지지도 않고 별로 위험하지도 않습니다. 









아두이노는 이런 짧은 시간의 ON/OFF 스위칭 신호를 발생시켜 주기도 하고

전압 체크나 온도 체크등의 역할을 하게 됩니다. 

스위칭 신호만 발생시켜도 용접하는 데는 무리가 없기 때문에 555 타이머를 이용한 회로도 있습니다. 





https://blog.naver.com/kikch/221435954972

회로는 많은 곳에서 참조했지만 아두이노와 연결해서 사용하는 개념은 위 블로그를 많이 참조했습니다. 



728x90

+ Recent posts