大家都知道,打印完毕一个模型通常都需要好几个小时甚至几十个小时,人总不能一直盯着吧。如果打印完毕后不及时关机,一方面持续耗电,一方面也降低设备寿命;在家中持续发出声光对家人也有一定影响。
我使用的是极光尔沃的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 sendwave@163.com
* 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);
}
}
}