이벤트
Quest 1
온도 자동 제어 3D 프린터 챔버 작성자 : PVT

 오픈형 3D 프린터를 사용하다 보면 큰 출력물의 경우 수축되는 문제로 출력이 실패하는 경우가 상당히 많습니다. 특히 ABS 재질을 사용하는 경우 수축의 문제가 매우 심각하여 사용을 포기하기도 합니다.

 일반적으로 이러한 문제를 해결하기 위해서3D 프린터를 외부에서 감싸주고 외부와 내부 공기 흐름을 차단해주는 챔버를 사용합니다. 시중에 판매하는 경우도 있고 직접 자작하는 경우도 있는데 특히 내부 온도를 설정하고 설정된 온도로 제어해주는 사례를 찾기 힘들었습니다. 그리하여 내부 온도를 제어해주는 3D 프린터 챔버를 제작하게 되었습니다.

 

  1. 설계 아이디어

 

 

  1. 제어기 제작

 2개의 7-segment를 통해서 두 자리 수의 현재 온도 또는 설정 온도를 표시합니다. 설정 온도 UP/DOWN 버튼을 누르면 설정 온도가 깜박임으로 표시되며 사용자의 버튼 조작을 감지하여 설정 온도 표시 상태를 유지하며 일정시간 이상 조작이 이루어지지 않으면 다시 현재 온도 표시 모드로 전환합니다. 설정 온도는 EEPROM에 저장하여 챔버 전원이 꺼지더라도 설정 값은 그대로 유지됩니다. 제어기는 현재 온도와 설정 온도를 비교하여 Heating Bed와 Fan의 On/Off를 결정하며 챔버 내부 온도가 사용자 설정 온도를 추종하도록 지속적으로 제어합니다. 왼쪽의 가변 볼륨은 내부 LED Bar 조명의 밝기를 조절하며 내부의 3D 프린터 동작을 야간에도 확인할 수 있도록 하였습니다.

 

  1. 회로 제작

 

  1. 동작 영상

 

  1. 소스 코드
// Name   : 3D_Printer_Chamber_Thermostat_V1.ino
// Device : ATmega328P (Arduino UNO)
// Created: 2022-03-02
// Author : H. S. Lee


#include 


#define FND_A                                    2                             // FND A pin
#define FND_B                                    3                             // FND B pin
#define FND_C                                    4                             // FND C pin
#define FND_D                                    5                             // FND D pin
#define FND_E                                    6                             // FND E pin
#define FND_F                                    7                             // FND F pin
#define FND_G                                    8                             // FND G pin
#define FND_1ST_DIGIT                            9                             // FND 1st digit cathode common pin
#define FND_2ND_DIGIT                            10                            // FND 2nd digit cathode common pin
#define LED                                      11                            // LED PWM pin
#define FAN                                      12                            // Fan on/off pin
#define HEATING_BED                              13                            // Heating bed on/off pin

#define LM35D_VOUT                               A0                            // LM35D Vout analog pin
#define VOLUME_LIGHT                             A1                            // Light volume analog pin
#define SW_UP                                    A2                            // Up switch pin
#define SW_DOWN                                  A3                            // Down switch pin


const unsigned char seven_seg_digits_decode_gfedcba[75] = {                    
	0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x3D,
	0x76, 0x30, 0x1E, 0x75, 0x38, 0x55, 0x54, 0x5C, 0x73, 0x67, 0x50, 0x6D,
	0x78, 0x3E, 0x1C, 0x1D, 0x64, 0x6E, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x3D, 0x76, 0x30, 0x1E, 0x75,
	0x38, 0x55, 0x54, 0x5C, 0x73, 0x67, 0x50, 0x6D, 0x78, 0x3E, 0x1C, 0x1D,
	0x64, 0x6E, 0x5B
};

int setTemp;
float currentTemp = 0;
float displayTemp = 0;

int digitSel = 0;
unsigned long lastTime_FND_Update = 0;  
unsigned long lastTime_SwitchCheck = 0;            

int mode_TempSet = 0;
int disable_UpSwitch = 0;
int disable_DownSwitch = 0;
int disable_LightSwitch = 0;


void update_FND(int digit, int data)
{
	digitalWrite(FND_1ST_DIGIT, LOW);
	digitalWrite(FND_2ND_DIGIT, LOW);

	if(seven_seg_digits_decode_gfedcba[data] & (0x01 << 0)) digitalWrite(FND_A, HIGH);
	else digitalWrite(FND_A, LOW);

	if(seven_seg_digits_decode_gfedcba[data] & (0x01 << 1)) digitalWrite(FND_B, HIGH);
	else digitalWrite(FND_B, LOW);

	if(seven_seg_digits_decode_gfedcba[data] & (0x01 << 2)) digitalWrite(FND_C, HIGH);
	else digitalWrite(FND_C, LOW);

	if(seven_seg_digits_decode_gfedcba[data] & (0x01 << 3)) digitalWrite(FND_D, HIGH);
	else digitalWrite(FND_D, LOW);

	if(seven_seg_digits_decode_gfedcba[data] & (0x01 << 4)) digitalWrite(FND_E, HIGH);
	else digitalWrite(FND_E, LOW);

	if(seven_seg_digits_decode_gfedcba[data] & (0x01 << 5)) digitalWrite(FND_F, HIGH);
	else digitalWrite(FND_F, LOW);

	if(seven_seg_digits_decode_gfedcba[data] & (0x01 << 6)) digitalWrite(FND_G, HIGH);
	else digitalWrite(FND_G, LOW);

	if(digit == 0) digitalWrite(FND_1ST_DIGIT, HIGH);
	else if(digit == 1) digitalWrite(FND_2ND_DIGIT, HIGH);
}


void setup()
{
	Serial.begin(115200);      
    
	pinMode(FND_A, OUTPUT);
	pinMode(FND_B, OUTPUT);
	pinMode(FND_C, OUTPUT);
	pinMode(FND_D, OUTPUT);
	pinMode(FND_E, OUTPUT);
	pinMode(FND_F, OUTPUT);
	pinMode(FND_G, OUTPUT);
	pinMode(FND_1ST_DIGIT, OUTPUT);
	pinMode(FND_2ND_DIGIT, OUTPUT);
    pinMode(LED, OUTPUT);
    pinMode(FAN, OUTPUT);
    pinMode(HEATING_BED, OUTPUT);
    
    pinMode(LM35D_VOUT, INPUT);
    pinMode(VOLUME_LIGHT, INPUT);
    pinMode(SW_UP, INPUT_PULLUP);
	pinMode(SW_DOWN, INPUT_PULLUP);
	
	digitalWrite(FAN, LOW);                                                    // Fan off
    digitalWrite(HEATING_BED, LOW);                                            // Heating bed off

	EEPROM.get(0, setTemp);

	if(setTemp > 80 || setTemp < 0) {                                          // Limit user set temperature
		setTemp = 35;
		EEPROM.put(0, setTemp);
	}
}


float get_Temperature()
{
	static float input[32] = {0.0, };
	static float total = 0.0;
	static int index = 0;
	float temp;

	total -= input[index];                                        
    #if false
	input[index] = (float)analogRead(LM35D_VOUT) * (110.0 / 1023.0);
    #else
    input[index] = (float)analogRead(LM35D_VOUT) * (500.0 / 1023.0);
    #endif
    total += input[index];                         
    
	if(++index > 31) index = 0;

    temp = total / 32.0;
    
	#if true
	Serial.println("Temperature: " + String(temp, 2) + " ˚C");
	#endif

    return temp;
}


void loop()
{
	unsigned long time = millis();                                             // Current time in msec

	if(Serial.available()) {
		char rxData = Serial.read();
		 
		Serial.write(rxData);
	}

	if((time - lastTime_FND_Update) > 9) {                                     // Execute every 10 msec
		int digit[2];                                                          // FND digit data
        
        lastTime_FND_Update = time;
        
        currentTemp = get_Temperature();                                       // Current temperature in ˚C
        if((currentTemp - displayTemp > 0.5) || (currentTemp - displayTemp < -0.5)) displayTemp = currentTemp;
        
		if(mode_TempSet > 0) {                                                 // Temperature set mode
			mode_TempSet--;

			if(((mode_TempSet % 30) > 14) || (mode_TempSet > 320)) {
				digit[1] = setTemp / 10;
				digit[0] = setTemp % 10;
			}
			else {
				digit[0] = 10;                                                 
				digit[1] = 10;                                                 
			}
		}
		else {                                                                 // Current temperature display mode
            int temp = round(displayTemp);

			digit[1] = temp / 10;
			digit[0] = temp % 10;
		}

		if(++digitSel > 1) digitSel = 0;
		
		update_FND(digitSel, digit[digitSel]);
	}
	
	if((time - lastTime_SwitchCheck) > 19) {                                    // Execute every 20 msec
		lastTime_SwitchCheck = time;

		if(digitalRead(SW_UP) == LOW) {
			if(disable_UpSwitch > 0) disable_UpSwitch--;
			else {
				disable_UpSwitch = 10;
                
				if(mode_TempSet > 0) {
					if(setTemp < 80) {
						setTemp++;
						EEPROM.put(0, setTemp);                                // Save to EEPROM
					}
				}

                mode_TempSet = 350;
			}
		}
		else disable_UpSwitch = 0;
		
		if(digitalRead(SW_DOWN) == LOW) {
			if(disable_DownSwitch > 0) disable_DownSwitch--;
			else {
				disable_DownSwitch = 10;
                
				if(mode_TempSet > 0) {
					if(setTemp > 0) {
						setTemp--;
						EEPROM.put(0, setTemp);                                // Save to EEPROM
					}
				}

                mode_TempSet = 350;
			}
		}
		else disable_DownSwitch = 0;

        analogWrite(LED, map(analogRead(VOLUME_LIGHT), 0, 1023, 0, 255));

        if(round(displayTemp) < setTemp) digitalWrite(HEATING_BED, HIGH);
        else digitalWrite(HEATING_BED, LOW);
        
        if(round(displayTemp) > (setTemp - 5)) digitalWrite(FAN, HIGH);
        else digitalWrite(FAN, LOW);
    }
}

 

첨부파일 : 온도 자동 제어 3D 프린터 챔버.pdf