PLC+Arduino实战笔记05:金属到位,LED才亮

2026-10-165

PLC+Arduino实战笔记05:金属到位,LED才亮

 

前几篇已经完成了PLC启动、停止、自保持、3秒延时和状态灯显示。这一篇继续往前走一步:加入接近开关,让PLC根据现场检测结果决定是否允许Arduino点亮LED。arduino C和C#的写法在前面部分很相似,实际是会了C,学工业C#会容易的多。本系列将通过52节课直达工业机器视觉前置课程。

 

本次实验的核心是:准备完成,不代表立即执行;工件到位后,才允许输出。

PLC+Arduino实战笔记05:金属到位,LED才亮_image_1.webp

一、本次要实现的效果

保留前面的启停与延时逻辑,只增加一个“金属工件到位”的条件。

按下启动按钮
    ↓
PLC保持启动状态
    ↓
等待3秒,准备完成
    ↓
检测金属是否到位
    ├─ 没有金属 → Arduino LED不亮
    └─ 金属到位 → Arduino LED亮

 

准备完成以后,移走金属,Arduino LED熄灭;再次靠近,LED再次点亮。按停止按钮,则撤销启动状态和输出。

这一篇不加电机、计数和超时报警,先把“检测条件控制输出”这一条链路跑通。

二、实验硬件与分工

本次使用的硬件:

  • 西门子S7-200 SMART CR40 PLC
  • 金属检测用接近开关
  • NPN转PNP信号转换器
  • 24V输入光耦隔离模块
  • Arduino
  • LED及其配套限流电路
  • 原有启动、停止按钮和状态指示灯

各部分分工如下:

 

部件本次作用
接近开关检测金属工件是否到位
NPN转PNP转换器使传感器信号匹配现有PLC输入接法
PLC完成启停、自保持、3秒准备和条件判断
光耦隔离模块将PLC侧信号隔离后传给Arduino
Arduino读取许可信号,控制LED显示

控制权仍然在PLC。Arduino不另做一套启动、延时或传感器判断,只负责接收PLC的最终许可并显示。

三、实际信号链路

本次验证后的输出地址是Q1.5。

接近开关
    ↓
NPN转PNP转换器
    ↓
PLC物体检测输入
    ↓
启动保持+准备完成+工件到位
    ↓
Q1.5
    ↓
隔离模块输入侧
    ↓
隔离模块O1 → Arduino D4
    ↓
Arduino D8 → LED

 

 

本机使用的对应关系:

 

项目地址/引脚
PLC启动保持M10.0
3秒准备定时器T37
准备完成状态M10.2
PLC到Arduino的输出Q1.5
隔离模块输出接ArduinoD4
Arduino LED控制D8

传感器的PLC输入地址应以实际接线和在线监控确认结果为准,不在这里把端子编号直接当成程序地址。

接线时,PLC侧24V不能直接进入Arduino数字引脚。光耦模块的输入电压、输出侧供电和端子定义,也需要按实际模块规格确认。

四、PLC逻辑:在原输出前增加一个条件

前面已经验证的启停和3秒延时网络保持不变。本篇的主要变化,是在最终输出前增加工件检测条件。

文字梯形图:

  M10.0           T37         工件到位
───| |────────────| |────────────| |────────( Q1.5 )
  已启动        准备完成       检测有效       Arduino许可

 

 

对应逻辑:

Arduino许可
= 已启动
AND 3秒准备完成
AND 工件到位

 

PLC+Arduino实战笔记05:金属到位,LED才亮_image_2.webp

这里没有对Q1.5做自保持。因此,准备完成后,工件一旦移走,检测条件不再成立,Q1.5就断开。

要注意区分两个状态:

  • 准备完成:表示3秒准备过程已经结束。
  • 允许执行:还需要工件到位,才给Arduino发送许可。

所以,PLC侧表示“准备完成”的绿灯可以保持亮着,而Arduino的LED仍然随着工件有无变化,两者含义不同。

五、Arduino:D4读取,D8显示

本次Arduino侧的引脚固定为:

const byte signalPin = 4; 
const byte ledPin = 8;

 

// 隔离模块 O1 → Arduino D4
// LED控制端   → Arduino D8

const byte signalPin = 4;
const byte ledPin = 3;

// 隔离模块动作时,D4的有效电平。
// 先用LOW;若实测亮灭相反,再改为HIGH。
const byte signalActiveLevel = LOW;

// LED点亮所需电平。
// 普通接法:D8 → 限流电阻 → LED → GND,使用HIGH。
// 若为低电平点亮的LED模块,改为LOW。
const byte ledOnLevel = HIGH;

int lastSignal = -1;

void setup() {
  Serial.begin(9600);

  pinMode(signalPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // 初始关闭LED
  digitalWrite(ledPin, ledOnLevel == HIGH ? LOW : HIGH);

  Serial.println("Test ready: input D4, LED D8");
}

void loop() {
  int signal = digitalRead(signalPin);
  bool active = (signal == signalActiveLevel);

  // LED跟随输入是否有效
  digitalWrite(
    ledPin,
    active ? ledOnLevel : (ledOnLevel == HIGH ? LOW : HIGH)
  );

  // 只在输入变化时打印
  if (signal != lastSignal) {
    Serial.print("D4 = ");
    Serial.print(signal);
    Serial.print(" | LED command = ");
    Serial.println(active ? "ON" : "OFF");

    lastSignal = signal;
  }

  delay(20);
}

程序思路很简单:

读取D4
    ↓
判断隔离输出是否有效
    ↓
控制D8上的LED

 

隔离模块可能是低电平有效,也可能采用其他输出方式,需要根据实际模块和读取结果确认,不能简单认为“读到HIGH一定代表PLC接通”。

调试时,可以通过串口查看D4读数:

金属移开 → 记录D4状态
金属靠近 → 记录D4状态

 

 

先确认输入是否变化,再判断LED控制逻辑,不要只靠灯的亮灭推测信号有没有到达。

六、本次踩坑:软件ON,不等于实物输出已经动作

这一篇最花时间的,不是增加检测触点,而是核对输出地址。

1. 检测对象用错了

一开始拿非金属物体测试,没有得到预期反应。

后来用金属靠近,传感器才触发。这次使用的是金属检测用接近开关,不能把它当成漫反射光电传感器使用。

这也提醒我:先确认传感器检测什么,再排查接线和程序。

2. 输出公共端没有有效供电

排查时发现:

L+有24V
4L没有24V

 

核对并接好L+到4L后,4L恢复24V。但隔离模块仍未得到预期信号,说明问题还没有完全解决。

3. 最终根因是程序地址与物理端子不对应

当时程序写的是:

Q4.5
在线监控显示ON,但实际接线位置是:

DQb区5号端子
本次CR40上的这个端子对应:

Q1.5
把输出线圈从Q4.5改成Q1.5后,问题解决。

这次最值得记住的一点是:

在线监控中的输出位为ON,只说明程序把该地址置成了1;还必须确认它对应的物理端子、公共端供电和外部回路。

 

4. 调试时不要让输入、输出共用一个引脚

Arduino调试中,还曾误把两个引脚都设为D4:

const byte signalPin = 4; 
const byte ledPin = 4;

这会让读取输入与驱动输出发生冲突。本次实际接线是D4输入、D8输出,两者必须分开。

七、第五课验收表

本课按以下现象检查:

 

测试操作预期结果
未启动,金属靠近Q1.5不接通,Arduino LED灭
启动后未满3秒,金属靠近仍不允许输出
准备完成,没有金属Q1.5断开,Arduino LED灭
准备完成,金属靠近Q1.5接通,Arduino LED亮
移走金属Q1.5断开,Arduino LED灭
金属仍在,按停止撤销许可,Arduino LED灭

拍摄时,把在线监控、接近开关和Arduino LED一起展示,会更容易看清“条件变化—PLC输出—实物显示”的对应关系。

八、下一篇

第五课解决的是:

工件没到,不允许执行。

 

下一篇准备增加一个等待期限:


准备完成
    ↓
开始等待工件
    ├─ 规定时间内到位 → 允许运行
    └─ 超时仍未到位 → 报警

先把现场输入读对、输出地址对应好,再往上增加流程逻辑。这次绕了不少路,但也留下了一条很有价值的排障记录。

创作许可协议

本项目采用 CC BY(署名) 进行许可。

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