大家都知道,打印完畢一個模型通常都需要好幾個小時甚至幾十個小時,人總不能一直盯着吧。如果打印完畢後不及時關機,一方面持續耗電,一方面也降低設備壽命;在家中持續發出聲光對家人也有一定影響。
我使用的是極光爾沃的Z603打印機,精度不錯,但是不具備打印完事後自動關機的功能。於是自己動手給它製作了一個自動關機模塊。
首先上圖,這是個模塊結構示意圖:
圖中只有手動開關和指示燈是顯現在機箱外部的,其他均隱藏在機箱內部會邊框內,不會影響外觀。
其中Arduino模塊作爲總控制系統,接收來自輕觸開關或手動開關的指令,以決定是否該通過繼電器控制220v電源斷電。降壓模塊是借用打印機24v內置開關電源降壓後給Arduino供電。指示燈用來指示當前狀態。
電路圖如下:
該圖已經很清楚了,就不再詳細敘述了。
控制原理就是:
1. 用戶通過原開關開機後,Arduino上電,程序控制繼電器閉合,此時用戶可以關閉原開關,依靠繼電器維持打印機繼續工作。此時LED燈常亮。
2. 當打印機打印完畢後,打印機會自動移動噴嘴y軸滑塊到最大邊緣位置,此時會觸動和壓住輕觸開關(開關固定在一個海綿座上,防止壓力過大造成損壞),此時Arduino會監測到此事件,開始持續每秒閃爍LED一次。繼續判斷該開關是否持續按壓30s(因爲有時候打印模型時也可能會短時間到達y軸最大位置,防止誤關機)。30s時間到,則Arduino控制LED快速閃爍3次,控制繼電器關閉總電源。
3. 如果用戶隨時想關機,可以按下手動開關。爲了防止誤碰開關造成關機,此處程序判斷需要持續按下該開關3s,系統纔會快速閃爍LED 3次,然後控制繼電器關閉總電源。
下面是實際改裝過程圖:
(1)降壓模塊,固定在風扇螺絲上
(2)兩個繼電器用膠布纏在一起,固定在開關附近
(3)燒錄程序並焊接完成的Arduino模塊,以及自己打印的LED與開關控制盒
(4)Arduino放入阻燃盒
(5)最終佈線完畢,僅留下LED和開關控制盒在外部,美觀&方便
下面是Arudino程序代碼:
/*
* 3D Printer AutoPowerDown
* Copyright [email protected]
* 2017-6-28
*/
const int triggerButtonPin = 9; // 限位觸發按鈕
const int manualButtonPin = 3; // 手動關機按鈕
const int relayPin = 2; // 繼電器
const int ledPin = 8; // the number of the LED pin
const int LOOP_DELAY_MSECONDS = 100; //每次循環毫秒數
const int TRIGGER_POWERDOWN_MSECONDS = 30000; //觸發按鈕多長時間關機
int triggerButtonState = 0; // variable for reading the pushbutton status
int manualButtonState = 0; // variable for reading the pushbutton status
int continuousTriggerCount = 0; //連續按下觸發按鈕的計數(時間)
void setup() {
// 開啓串行通信,並設置其頻率爲9600。
Serial.begin(9600);
int nTry = 0;
while (!Serial) {
nTry ++;
delay(50); // wait for serial port to connect. Needed for native USB port only
if(nTry > 20) //防止針對部分計算機和手機無法打開串口造成死鎖
break;
}
// 初始化LED和繼電器
pinMode(ledPin, OUTPUT);
pinMode(relayPin, OUTPUT);
// 並設置使用內部上拉電阻(注意,這裏使用內置的上拉電阻,無需再自己串聯電阻,但需要將button連接到GRND而不是5V,同時按下按鈕的電平狀態正好相反)
pinMode(triggerButtonPin, INPUT_PULLUP);
pinMode(manualButtonPin, INPUT_PULLUP);
delay(1000);
digitalWrite(ledPin, HIGH);
digitalWrite(relayPin, HIGH);
Serial.println("done.");
}
void loop() {
delay(LOOP_DELAY_MSECONDS);
triggerButtonState = !digitalRead(triggerButtonPin); //將狀態取反使用更方便
manualButtonState = !digitalRead(manualButtonPin); //將狀態取反使用更方便
//如果什麼按鈕都沒有按下
if ((triggerButtonState == LOW) && (manualButtonState == LOW)) {
continuousTriggerCount = 0;
return;
}
Serial.print("t:");
Serial.print(triggerButtonState);
Serial.print(" m:");
Serial.println(manualButtonState);
Serial.print("continuousTriggerCount:");
Serial.println(continuousTriggerCount);
//如果按下了觸發按鈕
if (triggerButtonState == HIGH)
{
continuousTriggerCount += 21;
//連續觸發按鈕時間達到了關機條件
if(continuousTriggerCount * LOOP_DELAY_MSECONDS > TRIGGER_POWERDOWN_MSECONDS)
{
Serial.println("Prepare Powerdown ... ");
//閃爍LED 5次
for(int i=0;i<5;i++)
{
digitalWrite(ledPin, LOW);
delay(200);
digitalWrite(ledPin, HIGH);
delay(200);
}
//關閉繼電器
digitalWrite(relayPin, LOW);
digitalWrite(ledPin, LOW);
Serial.println("Powerdowned.");
delay(50000);
}
digitalWrite(ledPin, LOW);
delay(1000);
digitalWrite(ledPin, HIGH);
delay(1000);
}
//如果按下了手動關機按鈕(持續3s會關機)
if (manualButtonState == HIGH)
{
continuousTriggerCount += 9; //30000/(9*1000)需要長按大約3s會關機
//連續觸發按鈕時間達到了關機條件
if(continuousTriggerCount * LOOP_DELAY_MSECONDS > TRIGGER_POWERDOWN_MSECONDS)
{
Serial.println("Soon will powerdown ... ");
//閃爍LED 5次
for(int i=0;i<5;i++)
{
digitalWrite(ledPin, LOW);
delay(200);
digitalWrite(ledPin, HIGH);
delay(200);
}
//關閉繼電器
digitalWrite(relayPin, LOW);
digitalWrite(ledPin, LOW);
Serial.println("Powerdowned.");
delay(50000);
}
}
}