PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮

2026-10-072

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮

 

PLC其实也是单片机,不过是叫工业单片机,而arduino是教育单片机。之所以放在一起,主要是好玩,打下兴趣的基础。而且arduino编程用的c语言和上位机用的C#同源,很多地方高度相似。本系列一反传统的先学梯形图,后学C#代码的方式,而是放在一起,两个同时进行。plc做主控制,arduino干细活的方式寓教于乐。方便有志于成为plc工程师和机器视觉工程师的人自学。

 

 

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_1.webp
  • 按一下PLC绿色按钮,Arduino外接LED亮。
  • 松开绿色按钮,LED继续亮。
  • 按下红色按钮,LED灭。
  • 松开红色按钮,LED保持灭。

看起来就是一盏灯,但调试时,PLC梯形图、隔离板、Arduino引脚和程序逻辑,任何一处没对齐,结果都会不一样。

本来想轻松点灯,最后发现:灯很小,坑不少。

一、这次要做什么

这次的目标不是“按住亮、松手灭”,而是实现一个基本的启保停实验:

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_2.webp

绿键:启动 松开绿键:保持运行 红键:停止 松开红键:保持停止

我使用西门子S7-200 SMART CR40作为主控,Arduino作为信号接收和显示端。

 

 

 

 

PLC按钮   ↓ PLC梯形图:启动、保持、停止   ↓ PLC输出Q1.5   ↓ 光耦隔离板   ↓ Arduino D10读取信号   ↓ Arduino D9控制外接LED

这里的分工很明确:

PLC决定是否运行,Arduino负责显示运行状态。

本次只做LED实验,不连接电机或其他危险执行机构。

二、地址和引脚分工

PLC侧

 

地址本实验用途已确认的状态
I0.0绿色启动按钮按下ON,松开OFF
I0.1红色停止按钮松开ON,按下OFF
M10.0内部运行状态位启动后保持,停止后清除
Q1.5发送运行状态到隔离板跟随M10.0

在我的软件里,输出符号名显示为CPU_输出13,对应的实际地址是Q1.5。符号名称和地址不是一回事,接线时要核对实际地址。3143

Arduino侧

 

引脚用途
D10读取隔离板输出O1
D9控制外接LED
GND连接隔离板输出侧GND及LED回路

外接裸LED采用下面的接法,并串联限流电阻:

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_3.webp

 

Arduino D9 → 限流电阻 → LED正极 LED负极 → Arduino GND

隔离板O1接D10,不再把外接LED也挂在D10上。

PLC侧和Arduino侧按隔离板的端子定义分别接线,不跨接两侧公共端;具体电源、电平和极性,以模块资料及实际测量为准。

三、PLC启保停梯形图

网络1:保存运行状态

 

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_4.webp

 

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_5.webp
PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_6.webp

 

读这段逻辑,可以用一句话:

红键未按下,并且“绿键按下”或者“已经处于运行状态”,就让M10.0保持ON。

 

实际动作过程:

  1. 初始状态下,M10.0为OFF。
  2. 按绿键,I0.0变为ON,M10.0线圈接通。
  3. M10.0的并联触点随之接通。
  4. 松开绿键,上面的启动支路断开,但下面的保持支路仍接通。
  5. 按红键,I0.1变为OFF,整个网络断开,M10.0变为OFF。

这里红键使用常开指令| |,是因为我的实际输入状态为“松开ON、按下OFF”。不要只凭按钮颜色或物理触点名称选择梯形图指令,要先确认输入状态。

网络2:驱动实际输出

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_7.webp

 

        M10.0 ────────| |──────────────────────( Q1.5 )

M10.0负责保存状态,Q1.5负责把状态输出给隔离板。

所以这次并不是Arduino自己记住“灯要亮”,而是PLC保持运行输出,Arduino持续读取并显示。

四、Arduino程序

本次成功版本使用D10读取信号,D9控制外接LED。

const byte SIGNAL_PIN = 10;  // 隔离板O1:只读输入
const byte LED_PIN = 9;      // 外接LED:输出控制

void setup() {
  pinMode(SIGNAL_PIN, INPUT);

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);  // 初始化时先关灯

  Serial.begin(9600);
  Serial.println("D10_INPUT_D9_LED_TEST");
}

void loop() {
  int level = digitalRead(SIGNAL_PIN);

  // 按之前的现象:绿色按钮按下时,D10为HIGH
  bool ledOn = (level == LOW);

  digitalWrite(LED_PIN, ledOn ? HIGH : LOW);

  Serial.print("D10=");
  Serial.print(level == HIGH ? "HIGH" : "LOW");
  Serial.print(" D9_LED=");
  Serial.println(ledOn ? "ON" : "OFF");

  delay(100);
}

 

这段代码没有自锁功能,只让外接LED跟随D10。

如果你的隔离模块输出极性相反,应先看串口和测量结果,再调整ledOn的判断条件;不能直接照搬本次HIGH亮的逻辑。

同样,代码中的LOW关灯,也以本帖所示的“D9→电阻→LED→GND”接法为前提。

五、今晚踩过的两个坑

坑1:LED接在输入引脚上

最初我把外接LED接在D10,但代码中:

 

pinMode(10, INPUT);

D10原本用于读取隔离板信号,程序控制的却是LED_BUILTIN。

结果是:我盯着外接LED看,程序控制的并不是它。

后来把两项任务分开:

 

D10:读信号 D9:控LED

这才把接线和程序对齐。

坑2:保持支路并联错了位置

最初的梯形图把M10.0并联在红键下面,而绿键仍串联在整个网络最前面:3143

PLC+Arduino实战笔记-02:绿键启动、红键停止,让LED松手也能亮_image_8.webp

所以绿键一松开,最前面的通路就断了。

当时的现象非常直接:

 

按绿键:PLC Q灯亮,Arduino LED亮 松开绿键:PLC Q灯灭,Arduino LED也灭

一直盯着Arduino改HIGH、LOW,并不能解决这个问题,因为PLC根本没保持输出。

把两个上方触点位置调整后,让保持支路绕过绿键,实验才成功。

今晚最重要的一句话:

自锁支路绕过启动按钮,停止按钮必须留在公共通路上。

 

六、验证与保存

最终按下面的顺序验证:

 

操作M10.0Q1.5Arduino外接LED
按绿键ONON亮
松开绿键保持ON保持ON继续亮
按红键OFFOFF灭
松开红键保持OFF保持OFF保持灭

这次排错最有效的动作,是先看PLC输出灯:

  • Q灯松开就灭:先查PLC保持逻辑。
  • Q灯保持,但Arduino灯不保持:再查隔离板、D10读数和LED输出。

另外,我也终于记牢了程序传输方向:

 

上传:PLC → 电脑,取回现有程序 下载:电脑 → PLC,写入修改后的程序

电脑上改完梯形图,要下载到PLC才会生效。成功后,把PLC工程、Arduino代码、接线照片和测试结果一起保存,下一次不用重新猜一遍。

这一课不复杂,但它让我真正分清了三件事:按钮输入是瞬时动作,M位保存运行状态,Q输出把状态送给外部设备。

按住灯亮是点动,松手还亮才是保持。

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(0)
- 没有更多了 -