车库自动推拉门
组件和用品
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
关于这个项目
背景
好吧,故事开始于有一天我到家的时候,我发现推拉门的遥控器坏了。 “电池!”我想,但不,这不是原因。我稍微调查了一下,当我取下门电机的盖子时,真是令人惊讶:在电子控制板和塑料支架之间的一个小空间里,一只小蜥蜴真的被碳化了(顺便说一下,我不打算从那个可怕的场景)。估计是小爬虫碰到了220V的扣子,产生了短路。结果是它死了,所有的电路都被烧毁了。
我已经从电路板上移除了一些可以保存在我的项目中使用的组件,但你可以在这张照片中看到它是如何结束的。
在那一刻,我决定这可能是制作 Arduino 项目和完全重建控制单元的完美借口。
警告
对于这个项目,您将不得不处理直接连接到 220V(或 110V)的组件。请注意,如果您对此类安装不是很熟练,这可能会很危险。请小心并谨慎行事。在连接到实际电机电路之前,请务必执行模拟。
组件和电路
该项目分为几个部分,但我在这里展示的是 Arduino 电路,它控制电机和信号灯的旋转,并考虑到限位开关传感器和安全光电管的状态。
起初,你可能认为它很容易构建和编程,但我可以向你保证,我必须克服很多困难,才使这个项目如此令人兴奋。
整个项目的其他重要组成部分是:
- 220V 电动马达和物理导轨和机构:这些不受蜥蜴动作的影响。
- 发出“打开”命令的远程无线电接收器:我使用了一个包含遥控器和接收器的商用现成单元。
- 220V 继电器支持电机使用的大电流。
- 主控单元由 Arduino Nano 和其他兼容配件制成,如 OLED 显示屏和继电器模块。这就是我在此门户中向您展示的内容。
我还添加了一些改进和几个自动化操作,这些操作未包含在商业原始控制单元中。
此项目的引脚排列
以下信息总结了组件的引脚以及如何连接它们:
如您所见,对于这个项目,我使用了直接连接到电路板上的 OLED 显示器。在正常工作条件下,该显示器位于机构和电子设备的保护罩内。因此,您无法看到它。实际上,此显示仅用于在调整设置时检查组件的状态并对代码进行微调(例如最大时间调整)。
该显示器提供的信息也可以发送到串行端口并从带有 Arduino IDE 软件的笔记本电脑检查,但我发现这个小显示器是一种很酷的方式来操作该装置,而无需使用任何笔记本电脑或其他装置。
OLED显示信息如下:
- 正在执行的代码阶段(开门、关门、等待“打开”命令、主循环等)
- 主要操作所用的时间(打开、再次关闭前等待和关闭)
- 光电池状态(当有人或某物处于关闭路径时处于活动状态)
- CLOSED 限位传感器状态(当门完全关闭时激活)
- OPENED 限位传感器状态(当门完全打开时激活)
- OPEN 命令信号(当按下遥控器并且无线电模块激活继电器时激活)
注意:我使用的 OLED 显示屏为 0.96 英寸,分辨率为 128 x 64 像素。该显示器可以使用 I2C 或 SPI 与控制设备(在本例中为 Arduino Nano)进行通信,我使用的是 SPI(串行外设接口)。
流程图
以下流程图以可读的方式总结了软件代码:
代码
- 英文软件代码版本
- 代码
英文软件代码版本C/C++
在这里,您可以看到所有注释都已翻译成英文的代码。它包括一个简短的词汇表,以便理解变量和标签的含义。/******************************** ***************************************** 滑动电动门的自动化**** ****************************************************** ***************//* 注释被翻译成英文,但为了帮助你理解变量和标签的名称,这里你有一个快速词汇“加泰罗尼亚语-英语” :Bucle principal =Main loop Sequencia Obertura =打开序列 Sequencia Tancament =关闭序列 Obrir =Open;奥伯特 =打开罐车 =关闭; Tancat =Closed Bombeta =灯泡 Llum =light Porta =Gate/door Avaria =Failure Temps =Time Recorregut =door travel*/// Oled Display 库#include#include #include #include // 我们定义控制电路使用的引脚int FOTOCELULA =2;int BOMBETA =5; //继电器1int TANCAT =7;int OBERT =3;int MOTOR_OBRIR =6; //继电器2int MOTOR_TANCAR =12; //Relay 3int OBRIR =4;//我们定义Oled显示器使用的引脚#define OLED_MOSI 11#define OLED_CLK 13#define OLED_DC 9#define OLED_CS 10#define OLED_RESET 8Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_RESET, OLED ,OLED_CS);//我们定义全局变量unsigned long TEMPS_PORTA_OBERTA =20000;unsigned long TEMPS_MAXIM_RECORREGUT =15000; //后面我们会重新定义这个值int interval =1000; // 间隔是我们等待的时间int TEMPS_DISPLAY =1; // 显示时间(以秒为单位)int DURADA =300; // 灯泡的 Cicle unsigned long previousMillis =0; // 跟踪自上次事件触发以来的时间 unsigned long currentMillis =millis();unsigned long TEMPS_LLUM =1000; // 灯泡状态的时间(以毫秒为单位)boolean LLUM =false; // 点亮或关闭布尔值 AVARIA =false; //门行程时间超过没有检测到限制 switchvoid setup() { // 关闭电机和灯 digitalWrite(MOTOR_OBRIR, HIGH);数字写入(MOTOR_TANCAR,高);数字写入(BOMBETA,高); // 我们为自动机初始化 pinMode(FOTOCELULA, INPUT_PULLUP); pinMode(TANCAT,INPUT_PULLUP); pinMode(OBERT,INPUT_PULLUP); pinMode(OBRIR,INPUT_PULLUP); pinMode(BOMBETA,输出); pinMode(MOTOR_OBRIR,输出); pinMode(MOTOR_TANCAR,输出); // 显示初始化 Serial.begin(9600); display.begin(SSD1306_SWITCHCAPVCC);显示。显示(); // 显示 Adafruit 初始标志 delay(1000); display.clearDisplay();显示。显示(); // 我们为显示准备文本大小(不重要,因为稍后它会重新定义) display.setTextSize(1); display.setTextColor(WHITE);}void loop() {BUCLE_PRINCIPAL:delay(2000);以前的米利斯 =米利斯();而 (digitalRead(OBRIR) ==HIGH) { display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("BUCLE PRINCIPAL ..."); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if (AVARIA and (millis() - previousMillis <60000)) { digitalWrite(BOMBETA, LOW); } else (digitalWrite(BOMBETA, HIGH)); }; // 我们等待直到发出打开命令,同时显示正在刷新显示传感器的状态 goto SEQUENCIA_OBERTURA;SEQUENCIA_OBERTURA:interval =28000; // 开门的最大时间(如果超过则表示失败) previousMillis =millis();数字写入(MOTOR_OBRIR,低);数字写入(BOMBETA,低);延迟(1000);A:如果(digitalRead(OBERT)==高){转到PORTA_OBERTA; }; if (digitalRead(OBRIR) ==LOW) { display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Esperant ordre per tancar"); // "等待关闭订单" display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示();数字写入(MOTOR_OBRIR,高);数字写入(BOMBETA,高);延迟(1000); while (digitalRead(OBRIR) ==HIGH) {}; //在发出OPEN命令之前什么都不做 goto SEQUENCIA_TANCAMENT; }; //---时间控制和显示刷新--------------- currentMillis =millis(); TEMPS_DISPLAY =(currentMillis - previousMillis) / 1000; display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Obrint porta"); display.setTextSize(2); display.setCursor(90, 0); display.println(TEMPS_DISPLAY); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if ((currentMillis - previousMillis)>=间隔) { digitalWrite(MOTOR_OBRIR, HIGH);阿瓦里亚 =真; // 转到 PORTA_OBERTA; }; //--light 闪烁频率控制------------------- if ((currentMillis - TEMPS_LLUM)>=1000) //低速闪烁 { LLUM =!LLUM;数字写入(BOMBETA,LLUM); TEMPS_LLUM =currentMillis; };转到 A;SEQUENCIA_TANCAMENT:间隔 =28000; // 关门的最大时间(如果超过则表示失败)!以前的米利斯 =米利斯();数字写入(MOTOR_TANCAR,低);数字写入(BOMBETA,低); if (digitalRead(TANCAT) ==LOW) {delay(1000);};B:if (digitalRead(TANCAT) ==HIGH) { digitalWrite(MOTOR_TANCAR, HIGH);数字写入(BOMBETA,高);转到 BUCLE_PRINCIPAL; }; if (digitalRead(OBRIR) ==LOW) { display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Esperant ordre per obrir"); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示();数字写入(MOTOR_TANCAR,高);数字写入(BOMBETA,高);延迟(1000); while (digitalRead(OBRIR) ==HIGH) {}; //在发出 OPEN 命令之前什么都不做 goto SEQUENCIA_OBERTURA; }; if (digitalRead(FOTOCELULA) ==HIGH) { digitalWrite(MOTOR_TANCAR, HIGH);延迟(1000);转到 SEQUENCIA_OBERTURA; }; //---时间控制和显示刷新--------------------- currentMillis =millis(); TEMPS_DISPLAY =(currentMillis - previousMillis) / 1000; display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Tancant porta"); display.setTextSize(2); display.setCursor(90, 0); display.println(TEMPS_DISPLAY); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if ((currentMillis - previousMillis)>=interval) { digitalWrite(MOTOR_TANCAR, HIGH);阿瓦里亚 =真;转到 BUCLE_PRINCIPAL; }; //--light 闪烁频率控制------------------ if ((currentMillis - TEMPS_LLUM)>=300) // 快速闪烁 { LLUM =!LLUM;数字写入(BOMBETA,LLUM); TEMPS_LLUM =currentMillis; };转到 B;PORTA_OBERTA:间隔 =30000; // 关门前的等待时间! (30秒进入车内...) previousMillis =millis();数字写入(MOTOR_OBRIR,高);延迟(500);C:如果(digitalRead(OBRIR)==低){转到SEQUNCIA_TANCAMENT; }; //---时间控制和显示刷新--------------------- currentMillis =millis(); TEMPS_DISPLAY =(currentMillis - previousMillis) / 1000; display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Porta Oberta completament"); display.setTextSize(2); display.setCursor(90, 0); display.println(TEMPS_DISPLAY); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if ((currentMillis - previousMillis)>=间隔) { 转到 SEQUENCIA_TANCAMENT; }; //--等待状态下的特殊复合闪烁频率------------------- //(2秒长周期之间100毫秒的短闪) if (LLUM ==false ) { 杜拉达 =100;否则杜拉达 =2000; if ((currentMillis - TEMPS_LLUM)>=DURADA) // { LLUM =!LLUM;数字写入(BOMBETA,LLUM); TEMPS_LLUM =currentMillis; };转到 C;}
代码C/C++
这是编译并上传到Arduino Nano的C++代码/********************************* ************************************ 每个 porta corredera motoritzada 的 Automatisme ****** ****************************************************** **********//// Llibreries per fer servir el display#include#include #include #include // Definim每个自动装置的引脚数 FOTOCELULA =2;int BOMBETA =5; //继电器1int TANCAT =7;int OBERT =3;int MOTOR_OBRIR =6; //继电器2int MOTOR_TANCAR =12; //Relay 3int OBRIR =4;// 每个显示器的定义引脚#define OLED_MOSI 11#define OLED_CLK 13#define OLED_DC 9#define OLED_CS 10#define OLED_RESET 8Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, Def//OLED_RESET);变量 globalsunsigned long TEMPS_PORTA_OBERTA =20000;unsigned long TEMPS_MAXIM_RECORREGUT =15000; //解压 ho redefinimint interval =1000; // 间隔是我们等待的时间int TEMPS_DISPLAY =1; // temps en segons per imprimir en pantallaint DURADA =300; // Cicle bombeta senyalitzaciounsigned long previousMillis =0; // 跟踪自上次事件触发以来的时间 unsigned long currentMillis =millis();unsigned long TEMPS_LLUM =1000; // temps en milisegons de estat llum senyalitzacioboolean LLUM =false; // Llum encessa si ON i apagada si OFFboolean AVARIA =false; //Excedit el temps de recorregut sense detectar finals de carreravoid setup() { // Inicialitzem els pin per automatisme porta pinMode(FOTOCELULA, INPUT_PULLUP); pinMode(TANCAT,INPUT_PULLUP); pinMode(OBERT,INPUT_PULLUP); pinMode(OBRIR,INPUT_PULLUP); pinMode(BOMBETA,输出); pinMode(MOTOR_OBRIR,输出); pinMode(MOTOR_TANCAR,输出); // Apaguem 电机 i llum digitalWrite(MOTOR_OBRIR, HIGH);数字写入(MOTOR_TANCAR,高);数字写入(BOMBETA,高); // 初始化显示 Serial.begin(9600); display.begin(SSD1306_SWITCHCAPVCC);显示。显示(); // Mostra pantalla incial de Adafruit delay(1000); display.clearDisplay();显示。显示(); // 准备每个文本显示 display.setTextSize(1); display.setTextColor(WHITE);}void loop() {BUCLE_PRINCIPAL:delay(2000);以前的米利斯 =米利斯();而 (digitalRead(OBRIR) ==HIGH) { display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("BUCLE PRINCIPAL ..."); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if (AVARIA and (millis() - previousMillis <60000)) { digitalWrite(BOMBETA, LOW); } else (digitalWrite(BOMBETA, HIGH)); }; //Esperem fins que premem OBRIR i anem refrescant pantalla per mostrar estat sensor goto SEQUENCIA_OBERTURA;SEQUENCIA_OBERTURA:interval =28000; // TEMPS MAXIM DE RECORREGUT PORTA OBRINT !!!!!!!!!以前的米利斯 =米利斯();数字写入(MOTOR_OBRIR,低);数字写入(BOMBETA,低);延迟(1000);A:如果(digitalRead(OBERT)==高){转到PORTA_OBERTA; }; if (digitalRead(OBRIR) ==LOW) { display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Esperant ordre per tancar"); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示();数字写入(MOTOR_OBRIR,高);数字写入(BOMBETA,高);延迟(1000); while (digitalRead(OBRIR) ==HIGH) {}; //没有 fem res fins que premem OBRIR goto SEQUENCIA_TANCAMENT; }; //--Control-de-temps-i-impressió-en-pantalla--------------------- currentMillis =millis(); TEMPS_DISPLAY =(currentMillis - previousMillis) / 1000; display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Obrint porta"); display.setTextSize(2); display.setCursor(90, 0); display.println(TEMPS_DISPLAY); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if ((currentMillis - previousMillis)>=间隔) { digitalWrite(MOTOR_OBRIR, HIGH);阿瓦里亚 =真; // 转到 PORTA_OBERTA; }; //--Control-de-cadencia-de-la-llum-intermitent----------------- if ((currentMillis - TEMPS_LLUM)>=1000) // Cadencia de la llum 间歇性 de senyalitzacio { LLUM =!LLUM;数字写入(BOMBETA,LLUM); TEMPS_LLUM =currentMillis; };转到 A;SEQUENCIA_TANCAMENT:间隔 =28000; // TEMPS MAXIM DE RECORREGUT PORTA TANCANT !!!!!!!!!以前的米利斯 =米利斯();数字写入(MOTOR_TANCAR,低);数字写入(BOMBETA,低); if (digitalRead(TANCAT) ==LOW) {delay(1000);};B:if (digitalRead(TANCAT) ==HIGH) { digitalWrite(MOTOR_TANCAR, HIGH);数字写入(BOMBETA,高);转到 BUCLE_PRINCIPAL; }; if (digitalRead(OBRIR) ==LOW) { display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Esperant ordre per obrir"); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示();数字写入(MOTOR_TANCAR,高);数字写入(BOMBETA,高);延迟(1000); while (digitalRead(OBRIR) ==HIGH) {}; //没有 fem res fins que premem OBRIR goto SEQUENCIA_OBERTURA; }; if (digitalRead(FOTOCELULA) ==HIGH) { digitalWrite(MOTOR_TANCAR, HIGH);延迟(1000);转到 SEQUENCIA_OBERTURA; }; //--Control-de-temps-i-impressió-en-pantalla--------------------- currentMillis =millis(); TEMPS_DISPLAY =(currentMillis - previousMillis) / 1000; display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Tancant porta"); display.setTextSize(2); display.setCursor(90, 0); display.println(TEMPS_DISPLAY); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if ((currentMillis - previousMillis)>=interval) { digitalWrite(MOTOR_TANCAR, HIGH);阿瓦里亚 =真;转到 BUCLE_PRINCIPAL; }; //--Control-de-cadencia-de-la-llum-intermitent----------------- if ((currentMillis - TEMPS_LLUM)>=300) // Cadencia de la llum 间歇性 de senyalitzacio { LLUM =!LLUM;数字写入(BOMBETA,LLUM); TEMPS_LLUM =currentMillis; };转到 B;PORTA_OBERTA:间隔 =30000; // TEMPS MAXIM ESPERANT AMB PORTA OBERTA !!!!!!!!!以前的米利斯 =米利斯();数字写入(MOTOR_OBRIR,高);延迟(500);C:如果(digitalRead(OBRIR)==低){转到SEQUNCIA_TANCAMENT; }; //--Control-de-temps-i-impressió-en-pantalla--------------------- currentMillis =millis(); TEMPS_DISPLAY =(currentMillis - previousMillis) / 1000; display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); display.println("Porta Oberta completament"); display.setTextSize(2); display.setCursor(90, 0); display.println(TEMPS_DISPLAY); display.setTextSize(1); display.setCursor(0, 20); display.print("Fotocel.lula:"); display.println(digitalRead(FOTOCELULA)); display.print("传感器TANCAT:"); display.println(digitalRead(TANCAT)); display.print("传感器奥伯特:"); display.println(digitalRead(OBERT)); display.print("Ordre OBRIR:"); display.println(!digitalRead(OBRIR));显示。显示(); if ((currentMillis - previousMillis)>=间隔) { 转到 SEQUENCIA_TANCAMENT; }; //--Control-de-cadencia-de-la-llum-intermitent----------------- if (LLUM ==false) { DURADA =100;否则杜拉达 =2000; if ((currentMillis - TEMPS_LLUM)>=DURADA) // Cadencia de la llum intermitent de senyalitzacio { LLUM =!LLUM;数字写入(BOMBETA,LLUM); TEMPS_LLUM =currentMillis; };转到 C;}
示意图
如何从主控制单元连接传感器、继电器和无线电模块的接线。 原理图_Kzy9lps55T.fzz屏幕截图来自fritzing原理图 这是使用的 Arduino 引脚列表以及如何将它们连接到其余组件。 pinouts_x7JmwoGJTY.txt这个硬件插件是对来自irshad2318的问题的回应(见这个项目的帖子)制造工艺