树莓派4通过Python与FT300力扭矩传感器通信故障排查
树莓派4读取FT300力扭矩传感器NoResponseError问题解决指南
问题描述
在Mac上使用pyFT300项目代码可正常读取FT300力扭矩传感器数据,但在树莓派4上启用串口后,使用/dev/ttyACM0端口运行相同代码时,抛出以下错误:
raise NoResponseError("No communication with the instrument (no answer)") minimalmodbus.NoResponseError: No communication with the instrument (no answer)
排查与解决步骤
1. 修复串口权限问题
树莓派普通用户默认无串口设备访问权限,执行以下命令添加用户到dialout组:
sudo usermod -aG dialout $USER
执行后重启树莓派生效,避免因权限不足导致串口读写失败。
2. 确认串口设备与参数匹配
- 检查实际端口路径:使用
ls /dev/ttyACM*或ls /dev/ttyUSB*查看适配器识别的真实端口,部分RS485适配器可能被识别为ttyUSB0而非ttyACM0。 - 核对通信参数:确保代码中波特率(19200)、数据位(8)、校验位(N)、停止位(1)与传感器手册要求完全一致,树莓派默认串口配置可能存在冲突。
3. 强制启用Modbus RTU模式
FT300传感器使用Modbus RTU协议,需在初始化minimalmodbus时明确开启该模式,取消代码中对应行的注释:
ft300.mode = mm.MODE_RTU
4. 调整串口超时与发送延迟
树莓派串口响应速度与Mac存在差异,尝试修改以下参数:
- 延长超时时间:将
TIMEOUT=1改为TIMEOUT=2 - 在发送停止流的0xff数据包后增加延迟,确保数据发送完成:
ser.write(packet) time.sleep(0.1) # 新增延迟 ser.close()
5. 检查硬件连接
- 确认RS485适配器的A/B线与传感器对应引脚正确连接,反接或交叉线会导致通信中断。
- 部分工业级RS485模块需要外部供电,检查适配器是否需额外供电才能正常工作。
6. 禁用树莓派内置串口控制台
即使启用了串口,树莓派默认可能将内置串口用作控制台,占用通信资源:
- 执行
sudo raspi-config - 选择
Interface Options->Serial Port - 选择否关闭串口控制台,是启用串口硬件
修改后的测试代码
#!/usr/bin/env python import minimalmodbus as mm import time from math import * import serial ###################### #Connection parameters ###################### print("hello") #Communication setup BAUDRATE=19200 BYTESIZE=8 PARITY="N" STOPBITS=1 TIMEOUT=2 # 延长超时时间 PORTNAME="/dev/ttyACM0" # 根据实际识别端口修改 SLAVEADDRESS=9 ############################ #Desactivate streaming mode ############################ ser=serial.Serial(port=PORTNAME, baudrate=BAUDRATE, bytesize=BYTESIZE, parity=PARITY, stopbits=STOPBITS, timeout=TIMEOUT) packet = bytearray() sendCount=0 while sendCount<50: packet.append(0xff) sendCount=sendCount+1 ser.write(packet) time.sleep(0.1) # 增加延迟确保发送完成 ser.close() #################### #Setup minimalmodbus #################### mm.BAUDRATE=BAUDRATE mm.BYTESIZE=BYTESIZE mm.PARITY=PARITY mm.STOPBITS=STOPBITS mm.TIMEOUT=TIMEOUT ft300=mm.Instrument(PORTNAME, slaveaddress=SLAVEADDRESS) ft300.debug=True # 开启调试查看通信报文 ft300.mode=mm.MODE_RTU # 强制启用RTU模式 #################### #Functions #################### def forceConverter(forceRegisterValue): force=0 forceRegisterBin=bin(forceRegisterValue)[2:] forceRegisterBin="0"*(16-len(forceRegisterBin))+forceRegisterBin if forceRegisterBin[0]=="1": force=-1*(int("1111111111111111",2)-int(forceRegisterBin,2)+1)/100 else: force=int(forceRegisterBin,2)/100 return force def torqueConverter(torqueRegisterValue): torque=0 torqueRegisterBin=bin(torqueRegisterValue)[2:] torqueRegisterBin="0"*(16-len(torqueRegisterBin))+torqueRegisterBin if torqueRegisterBin[0]=="1": torque=-1*(int("1111111111111111",2)-int(torqueRegisterBin,2)+1)/1000 else: torque=int(torqueRegisterBin,2)/1000 return torque #################### #Main program #################### if __name__ == '__main__': try: registers=ft300.read_registers(180,6) fxZero=forceConverter(registers[0]) fyZero=forceConverter(registers[1]) fzZero=forceConverter(registers[2]) txZero=torqueConverter(registers[3]) tyZero=torqueConverter(registers[4]) tzZero=torqueConverter(registers[5]) while True: registers=ft300.read_registers(180,6) fx=round(forceConverter(registers[0])-fxZero,0) fy=round(forceConverter(registers[1])-fyZero,0) fz=round(forceConverter(registers[2])-fzZero,0) tx=round(torqueConverter(registers[3])-txZero,2) ty=round(torqueConverter(registers[4])-tyZero,2) tz=round(torqueConverter(registers[5])-tzZero,2) print("***Press Ctrl+C to stop the program***") print(f"fx={fx}N fy={fy}N fz={fz}N tx={tx}N.m ty={ty}N.m tz={tz}N.m") time.sleep(0.5) except KeyboardInterrupt: print("Program ended") pass
内容的提问来源于stack exchange,提问作者Ricky Ortiz
相关产品推荐
相关产品推荐

