当前位置: 首页 > news >正文

工业一体机Linux系统部署实战:从系统安装到工业通信环境搭建

工业一体机是面向工业场景的集成化计算终端,通常预装Windows或Linux操作系统,支持串口通信、GPIO控制、工业总线协议等工业级接口。在ARM架构工业一体机上部署Linux系统并搭建工业通信开发环境,是工业自动化项目的常见基础工作。

之前在项目里给一台ARM架构(RK3568)的工业一体机部署Ubuntu系统,做Modbus TCP通信和串口数据采集。整个过程踩了不少坑,记录下来给需要的朋友参考。文中不涉及任何商业产品信息,纯粹是技术实战笔记。

## 系统安装与基础配置

RK3568平台通常出厂自带Android或Debian,但做工业开发我更习惯用Ubuntu。刷机工具用厂家的Rockchip烧录工具,把Ubuntu镜像烧到eMMC里。

烧录完成后第一件事,配置网络和SSH:

```bash
# 配置静态IP(工业现场通常用固定IP)
sudo nano /etc/netplan/01-netcfg.yaml
```

```yaml
network:
version: 2
ethernets:
eth0:
addresses:
- 192.168.1.100/24
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 114.114.114.114]
```

```bash
sudo netplan apply
```

然后装SSH方便远程操作:

```bash
sudo apt update
sudo apt install openssh-server -y
sudo systemctl enable ssh
```

## 串口环境配置

工业一体机的串口设备通常映射为`/dev/ttyS*`或`/dev/ttyUSB*`。先确认串口节点:

```bash
ls -l /dev/ttyS*
# 输出示例:
# crw-rw---- 1 root dialout 4, 64 Jul 22 09:00 /dev/ttyS0
# crw-rw---- 1 root dialout 4, 65 Jul 22 09:00 /dev/ttyS1
# crw-rw---- 1 root dialout 4, 66 Jul 22 09:00 /dev/ttyS2
```

确认串口能正常收发数据。用`stty`配置串口参数:

```bash
# 配置ttyS3为RS485模式,波特率9600
stty -F /dev/ttyS3 9600 cs8 -cstopb -parenb -crtscts

# 测试发送
echo -n "test data" > /dev/ttyS3

# 用cat监听接收
cat /dev/ttyS3 &
```

RS485的收发切换是个常见的坑。有些平台的RS485引脚控制需要通过ioctl切换,不是标准的硬件流控:

```c
#include <sys/ioctl.h>
#include <linux/serial.h>

// RS485收发方向切换
struct serial_rs485 rs485conf;
rs485conf.flags |= SER_RS485_ENABLED;
rs485conf.flags |= SER_RS485_RTS_ON_SEND; // 发送时拉高RTS
rs485conf.flags &= ~SER_RS485_RTS_AFTER_SEND; // 发送后拉低RTS
rs485conf.delay_rts_before_send = 1;
rs485conf.delay_rts_after_send = 1;
ioctl(fd, TIOCSRS485, &rs485conf);
```

## Modbus TCP通信环境搭建

工业通信最常用的协议就是Modbus,TCP版本跑在以太网上,部署简单。Python的`pymodbus`库很好用:

```bash
sudo apt install python3-pip -y
pip3 install pymodbus
```

写一个简单的Modbus TCP从站(Slave),模拟一个PLC设备响应主站请求:

```python
from pymodbus.server import StartTcpServer
from pymodbus.datastore import ModbusSlaveContext, ModbusServerBlock
from pymodbus.datastore import ModbusSequentialDataBlock

# 初始化数据存储区
store = ModbusSlaveContext(
di=ModbusSequentialDataBlock(0, [0]*100), # 离散输入
co=ModbusSequentialDataBlock(0, [0]*100), # 线圈
hr=ModbusSequentialDataBlock(0, [0]*100), # 保持寄存器
ir=ModbusSequentialDataBlock(0, [0]*100), # 输入寄存器
)

# 启动TCP从站,监听502端口
StartTcpServer(context=store, address=("0.0.0.0", 502))
```

再写一个主站(Master)轮询多个从站设备的示例:

```python
from pymodbus.client import ModbusTcpClient
import time

# 设备地址列表
devices = [
{"ip": "192.168.1.101", "port": 502, "unit_id": 1},
{"ip": "192.168.1.102", "port": 502, "unit_id": 2},
{"ip": "192.168.1.103", "port": 502, "unit_id": 3},
]

def poll_device(device):
client = ModbusTcpClient(device["ip"], port=device["port"], timeout=3)
if not client.connect():
print(f"[ERROR] 连接失败: {device['ip']}")
return None

try:
# 读取保持寄存器,地址0开始,读10个
result = client.read_holding_registers(0, 10, slave=device["unit_id"])
if result.isError():
print(f"[ERROR] 读取失败: {device['ip']}")
return None
return result.registers
finally:
client.close()

# 轮询采集
while True:
for dev in devices:
data = poll_device(dev)
if data:
print(f"{dev['ip']}: {data}")
time.sleep(1)
```

## GPIO控制

ARM平台的工业一体机一般有GPIO引脚,通过sysfs控制:

```bash
# 导出GPIO引脚(假设使用GPIO编号17)
echo 17 > /sys/class/gpio/export

# 设置为输出方向
echo out > /sys/class/gpio/gpio17/direction

# 设置高电平
echo 1 > /sys/class/gpio/gpio17/value

# 设置低电平
echo 0 > /sys/class/gpio/gpio17/value

# 取消导出
echo 17 > /sys/class/gpio/unexport
```

如果用Python控制更方便:

```python
import os

class GPIO:
def __init__(self, pin):
self.pin = pin
self.path = f"/sys/class/gpio/gpio{pin}"

def export(self):
if not os.path.exists(self.path):
with open("/sys/class/gpio/export", "w") as f:
f.write(str(self.pin))

def set_direction(self, direction):
with open(f"{self.path}/direction", "w") as f:
f.write(direction)

def write(self, value):
with open(f"{self.path}/value", "w") as f:
f.write(str(value))

def read(self):
with open(f"{self.path}/value", "r") as f:
return f.read().strip()

# 使用示例
led = GPIO(17)
led.export()
led.set_direction("out")
led.write(1) # 点亮
```

## 常见坑和解决方案

| 问题 | 原因 | 解决方案 |
|------|------|---------|
| 串口打不开 | 权限不足 | `sudo usermod -aG dialout $USER` |
| RS485收不到数据 | 方向切换时序 | 调整delay_rts参数 |
| Modbus超时 | 网络或从站无响应 | 设置合理的timeout和重试 |
| GPIO不可用 | 内核未编译驱动 | 检查设备树配置 |
| 串口名称变化 | udev规则未固定 | 写udev规则绑定物理端口 |

串口名称漂移的问题比较烦,插拔USB转串口设备后`/dev/ttyUSB0`可能变成`ttyUSB1`。解决方法是写udev规则:

```bash
# 查看设备串号
udevadm info -a -n /dev/ttyUSB0 | grep serial

# 创建udev规则
sudo nano /etc/udev/rules.d/99-usb-serial.rules
```

```
SUBSYSTEM=="tty", ATTRS{serial}=="FTS12345", SYMLINK+="ttyPLC01"
SUBSYSTEM=="tty", ATTRS{serial}=="A1001XYW", SYMLINK+="ttySensor01"
```

```bash
sudo udevadm control --reload-rules
sudo udevadm trigger
```

之后用`/dev/ttyPLC01`访问设备,不管插拔顺序怎么变,名称都固定。

## 常见问题(FAQ)

**Q:ARM架构工业一体机部署Linux系统有什么注意事项?**
A:需使用平台对应的Linux镜像,通过厂家烧录工具写入eMMC。部署后注意配置静态IP(工业现场固定地址)、安装SSH服务、配置串口权限(将用户加入dialout组)。部分平台需要通过设备树(Device Tree)配置GPIO和串口引脚复用,具体配置方式参考平台的BSP文档。

**Q:工业通信中RS485收发方向切换如何实现?**
A:Linux下通过serial_rs485结构体配合ioctl的TIOCSRS485命令实现硬件自动收发切换。关键参数包括SER_RS485_ENABLED(启用RS485模式)、SER_RS485_RTS_ON_SEND(发送时RTS电平)和delay_rts_before_send/after_send(方向切换延迟,单位毫秒)。不同平台时序要求不同,需根据实际波特率调整延迟参数。

**Q:Linux下如何固定USB转串口设备名称?**
A:通过编写udev规则,根据设备的serial号或其他唯一属性创建固定符号链接。使用udevadm info查询设备属性,在/etc/udev/rules.d/下创建规则文件,将特定serial的设备映射为固定名称如ttyPLC01。这样无论插拔顺序如何变化,设备名始终固定,保证应用程序引用正确。

http://www.cnnetsun.cn/news/3609763.html

相关文章:

  • Claude Code被曝重大隐患,揭开了算法安全的帷幕
  • Ubuntu开发环境搭建(Python-Go-Rust)
  • Google 连发三个新 Gemini 模型,官方宣传与网友差评落差大,Gemini 4 能救场吗?
  • 蓝速 AI 双屏翻译机国际版:全球口音精准适配与商务实效展示
  • 为什么你的AI配乐总被平台降权?——基于127万条审核日志的音频频谱分析报告(含可复用检测清单)
  • python数据可视化技巧的100个练习 -- 38. 交通流量数据可视化的网络流图
  • 下一代企业智能基座:为什么说「LLM 规划 + MCP 调度 + Agent 执行」= 未来标配?一、引言:从工具到系统的智能化跃迁在企业数字化转型的深水区,传统 IT 架构正面临决策滞后、资源割
  • 2026有实力的全球EMBA中立测评,民营企业家择校参考
  • Python企业内部数据治理流程自动化落地的构建路径【教学】
  • Spring Security掌握内容速忆(适用于初学者)
  • 华为鸿蒙免费铃声软件—小羊免费铃声
  • 基于人脸识别的无人值守自习室预约系统设计与实现
  • 高斯泼溅技术-从入门到精通
  • DeepSeek专家模式突破对话上限技巧,无缝衔接新对话!
  • 非结构化数据满天飞,90%的敏感数据藏在文档堆里,怎么让AI真正分得清?
  • 大模型分布式训练与显存优化核心技术解析
  • 因算力紧缺,月之暗面Kimi宣布暂停C端新用户订阅;ASML回应向全球员工发2万欧元股权激励;Qwen3.8-Max预览版上线 | 极客头条
  • 2026年英文论文翻译工具横评:5款主流方案实测对比与效率选型指南
  • UVM验证平台的死亡陷阱:从入门到放弃的那些坑
  • FreeRDP曝高危堆缓冲区溢出漏洞:wfreerdp客户端遭弃用,远程代码执行风险急剧上升
  • 【Springboot毕设全套源码+文档】基于JavaWeb的图书馆管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 下拉刷新库:通用下拉刷新与上拉加载组件(243)
  • 弹窗库:Toast、Loading、ActionSheet的统一封装(244)
  • C 语言 struct 内存对齐与面向对象:从 padding 到函数指针接口
  • 从“刷卡拥堵”到“秒级通行”:一张RFID电子校徽如何让校园管理有迹可循?
  • 2023三大开源AI工具实战:Dify、n8n与OpenClaw
  • 东莞商旅服务平台头部机构多维度能力梳理及选型参考
  • LLM Agent技术演进:从定制化到通用化
  • 解密企业通信安全防线:Avaya Aura 三层安全架构深度解析
  • LLM到Agent的技术演进与核心组件解析