error opening serial port

本文介绍了在Ubuntu 12.04系统中使用PL2303 USB转串口模块与51单片机通信时遇到的权限问题。当尝试打开串口设备文件/dev/ttyUSB0时出现权限拒绝错误,通过修改该设备文件的权限设置解决了此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境:

ubuntu 12.04  64bit

pl2303 USB转串口


在使用一个串口程序与51单片机通信时,提示

error opening serial port '/dev/ttyUSB0' permission denied


解决方法:

改变ttyUSB0的执行权限# sudo chmod 777 /dev/ttyUSB0

可以使用 # ls -l /dev/ttyUSB* 察看相关信息

帮我把如下代码改写为python2环境:#!/usr/bin/env python # -*- coding: UTF-8 -*- # --------------------------------------------------------- # Copyright (C), 2025, Lianzhou International Co.,Ltd. # # description: GWSChamberCtrl.py for GWS chamber # Author: zhouziqi@tp-link.com.hk # history: # 2025/6/9 14:20, zhouziqi@tp-link.com.hk, Created. # --------------------------------------------------------- import serial import time import logging from typing import List class Program: """老化箱程序步骤模型""" def __init__(self, temperature: float, humidity: float, hour: int, minute: int): self.temperature = temperature self.humidity = humidity self.hour = hour self.minute = minute class GWSChamberCtrl(object): #串口命令常量 COMMAND_GET_TEMP = "1, TEMP?" COMMAND_GET_HUMI = "1, HUMI?" COMMAND_GET_PRGM = "1, PRGM SET?" COMMAND_STOP_DEV = "1, MODE, OFF" COMMAND_EXECUTE_PROGRAM = "1, PRGM, RUN, RAM:1, STEP1" COMMAND_SET_CONSTANT_TEMP = "1, TEMP" COMMAND_SET_MODE_CONSTANT = "1, MODE, CONSTANT" # 特殊响应标识 NA_PREFIX = "NA:" NOT_READY_CODE = "NA:CONT NOT READY-1" # 设置成功响应标识 OK_SIGN = "[b'OK:1" def __init__(self, port, baudrate=19200, bytesize=8, stopbits=1, parity=None): self.logger = logging.getLogger() if not logging.root.handlers: self.logger.setLevel(logging.INFO) self.console_handler = logging.StreamHandler() self.formatter = logging.Formatter(u"[%(asctime)s] [%(levelname)s] %(message)s", u"%m-%d %H:%M:%S") self.console_handler.setFormatter(self.formatter) self.logger.addHandler(self.console_handler) self.port = port self.baudrate = baudrate self.bytesize = bytesize self.stopbits = stopbits self.parity = parity try: self.ser = self.open_serial(port=self.port, baudrate=self.baudrate, bytesize=self.bytesize, stopbits=self.stopbits, parity=self.parity) self.logger.info("Serial Port Opened") except Exception as e: self.logger.error("Error Opening Serial Port: ", e) def SInterval(self): """命令执行间隔延时""" time.sleep(0.5) def open_serial(self, port, baudrate, bytesize, stopbits, parity): """open serial connection""" try: if port is None: port = self.port else: self.port = port if baudrate is None: baudrate = self.baudrate else: self.baudrate = baudrate if bytesize is None: bytesize = self.bytesize else: self.bytesize = bytesize if stopbits is None: stopbits = self.stopbits else: self.stopbits = stopbits if parity is None: parity = self.parity else: self.parity = parity bytesize = serial.EIGHTBITS if bytesize == 8 else serial.SEVENBITS parity = serial.PARITY_NONE if parity is None else parity stopbits = serial.STOPBITS_ONE if stopbits == 1 else serial.STOPBITS_TWO ser = serial.Serial(port=port, baudrate=baudrate, bytesize=bytesize, parity=parity, stopbits=stopbits, timeout=1, xonxoff=False) self.logger.info('%s has opened, baudrate is %s' % (port, baudrate)) return ser except serial.SerialException as e: self.logger.error('Can\'t open %s: %s' % (port,e)) raise def send_command(self, command): """send command to the serial port""" try: if self.ser is not None and self.ser.isOpen(): self.ser.write(command.encode('utf-8')) self.logger.info('Send command:<%s>' % command) time.sleep(0.5) data = self.receive_data() return data else: self.logger.error('Serial port is closed or not exist') except Exception as e: self.logger.error('Error sending command <%s>: %s' % (command, e)) raise def receive_data(self): """get data from the serial port""" try: if self.ser is not None and self.ser.isOpen(): data = self.ser.readlines() self.logger.info('Receive data:<%s>' % data) return data else: self.logger.error('Serial port is closed or not exist') return None except Exception as e: self.logger.error('Error receiving data: %s' % e) raise def close_serial(self): """close the serial connection""" try: if self.ser is not None and self.ser.isOpen(): self.ser.close() self.logger.info('Serial port has been closed') else: self.logger.error('Serial port is already closed') except Exception as e: self.logger.error('Error closing serial port: %s' % e) raise def get_temperature(self): """ :get chamber\'s temperature :return: [monitored temperature, target temperature, highlimit temperature, lowlimit temperature] """ try: # 发送温度查询命令 response = self.send_command(command=self.COMMAND_GET_TEMP) # 验证响应格式 if not response or not isinstance(response, list): raise ValueError(f"Invalid response format: {response}") # 从列表中取出第一个元素(字符串) data_str = str(response[0].decode('utf-8')) # 分割字符串并转换为浮点数 temp_values = data_str.strip().split(',') # 验证分割结果数量 if len(temp_values) != 4: raise ValueError(f"Expected 4 temperature values, got {len(temp_values)}") # 将每个值转换为浮点数 temperatures = [float(value.strip()) for value in temp_values] return temperatures except ValueError as ve: self.logger.error(f"Temperature value error: {ve}") # 可在此处添加默认值返回或重新抛出异常 raise except Exception as e: self.logger.error(f"Error getting temperature: {e}") raise def get_current_temperature(self,temperature_data): """ 从温度数据列表中获取第一个数据(当前温度) 参数: temperature_data (list): 包含温度数据的列表,格式为 [监控温度, 目标温度, 高温限制, 低温限制] 返回: float: 当前温度值 """ try: # 验证输入是否为列表 if not isinstance(temperature_data, list): raise TypeError("参数必须是列表类型") # 验证列表是否非空 if len(temperature_data) < 1: raise IndexError("温度数据列表不能为空") # 获取第一个元素并赋值给current_temp current_temp = temperature_data[0] # 验证数据类型是否是数值 if not isinstance(current_temp, (int, float)): raise TypeError("第一个温度数据必须是数值类型") return current_temp except Exception as e: self.logger.error(f"Error getting current temperature: {e}") raise def get_humidity(self): """ :get chamber\'s humidity :return: [monitored humidity, target humidity, highlimit humidity, lowlimit humidity] """ try: # 发送湿度查询命令 response = self.send_command(command=self.COMMAND_GET_HUMI) response_decode = response[0].decode('utf-8') if response_decode == self.NOT_READY_CODE: self.logger.error("无法查询湿度: 设备不支持或未开启湿度控制") response = [0, 0, 0, 0] return response # 验证响应格式 if not response or not isinstance(response, list): raise ValueError(f"Invalid response format: {response}") # 从列表中取出第一个元素(字符串) data_str = str(response[0].decode('utf-8')) # 分割字符串并转换为浮点数 humi_values = data_str.strip().split(',') # 验证分割结果数量 if len(humi_values) != 4: raise ValueError(f"Expected 4 humidity values, got {len(humi_values)}") # 将每个值转换为浮点数 humiditys = [float(value.strip()) for value in humi_values] return humiditys except ValueError as ve: self.logger.error(f"humidity value error: {ve}") # 可在此处添加默认值返回或重新抛出异常 raise except Exception as e: self.logger.error(f"Error getting humidity: {e}") raise def get_current_humidity(self,humidity_data): """ 从湿度数据列表中获取第一个数据(当前湿度) 参数: humidity_data (list): 包含湿度数据的列表,格式为 [监控湿度, 目标湿度, 高温限制, 低温限制] 返回: float: 当前湿度值 """ try: # 验证输入是否为列表 if not isinstance(humidity_data, list): raise TypeError("参数必须是列表类型") # 验证列表是否非空 if len(humidity_data) < 1: raise IndexError("湿度数据列表不能为空") # 获取第一个元素并赋值给current_humi current_humi = humidity_data[0] # 验证数据类型是否是数值 if not isinstance(current_humi, (int, float)): raise TypeError("第一个湿度数据必须是数值类型") return current_humi except Exception as e: self.logger.error(f"Error getting current humidity: {e}") raise def constant_mode_set(self, constant_target_temp, constant_target_humi): """ 设置定值模式下老化箱的目标温度和湿度 参数: constant_target_temp (float): 要设置的目标温度值 constant_target_humi (float): 要设置的目标湿度值 返回: str: 发送到老化箱的完整指令字符串 功能: 根据输入的目标温度值,构建"1, TEMP, SX.X"格式的指令 根据输入的目标湿度值,构建"1, HUMI, SX.X"格式的指令 """ try: # 温度设置 # 验证输入是否为数值类型 if not isinstance(constant_target_temp, (int, float)): raise TypeError("目标温度必须是数值类型") # 格式化温度值为带一位小数的字符串 formatted_temp = f"{constant_target_temp:.1f}" # 构建完整的指令字符串 constant_temp_command = f"1, TEMP, S{formatted_temp}" # 湿度设置 # 验证输入是否为数值类型 if not isinstance(constant_target_humi, (int, float)): raise TypeError("目标湿度必须是数值类型") # 格式化湿度值为带一位小数的字符串 formatted_humi = f"{constant_target_humi:.1f}" # 构建完整的指令字符串 constant_humi_command = f"1, HUMI, S{formatted_humi}" # 发送指令到设备 # 通过send_command方法来实际发送指令 self.send_command(command=constant_temp_command) time.sleep(1) self.send_command(command=constant_humi_command) time.sleep(1) self.send_command(command=self.COMMAND_SET_MODE_CONSTANT) time.sleep(1) time.sleep(1) # 检查设置是否成功 temp_result_data = self.get_temperature() time.sleep(1) current_temp_set = temp_result_data[1] self.logger.info(f"current temp set: {current_temp_set}") # 当前设置温度是否与预期一致 if current_temp_set != constant_target_temp: raise ValueError(f"Expected set temp to {constant_target_temp}, current {current_temp_set}") humi_result_data = self.get_humidity() time.sleep(1) current_humi_set = humi_result_data[1] self.logger.info(f"current humi set: {current_humi_set}") # 当前设置湿度是否与预期一致 if current_humi_set != constant_target_humi: raise ValueError(f"Expected set humi to {constant_target_humi}, current {current_humi_set}") except Exception as e: self.logger.error(f"设置出错: {e}") raise def WriteProgram(self, program_list: List[Program]): """向设备写入程序""" # 发送开始编辑命令 try: self.send_command("1, PRGM DATA WRITE, PGM1, EDIT START") step = 1 for program in program_list: commands = self.ConvertProgramToCommands(program, step) for cmd in commands: # 检查命令长度限制 if len(cmd) > 50: self.logger.info(f"命令过长,可能被截断: {cmd}") if not self.send_command(cmd): self.logger.info("程序写入失败") return False step += 1 self.SInterval() # 步骤间隔 # 发送结束编辑命令 self.send_command("1, PRGM DATA WRITE, PGM1, END, OFF") self.send_command("1, PRGM DATA WRITE, PGM1, EDIT END") self.logger.info("程序写入成功") return True except Exception as e: self.logger.error(f"设置出错: {e}") raise def ConvertProgramToCommands(self, program: Program, step: int): """ 将程序步骤转换为命令 :param program: 程序步骤 :param step: 步骤编号 :return: 命令列表 """ try: commands = [] step_cmd = f"STEP{step}" if program.temperature != 0: temp_cmd = ( f"1, PRGM DATA WRITE, PGM1, {step_cmd}, " f"TEMP{program.temperature}, " f"TIME{program.hour:02d}:{program.minute:02d}" ) commands.append(temp_cmd) if program.humidity != 0: humi_cmd = ( f"1, PRGM DATA WRITE, PGM1, {step_cmd}, " f"HUMI{program.humidity}, " f"TIME{program.hour:02d}:{program.minute:02d}" ) commands.append(humi_cmd) return commands except Exception as e: self.logger.error(f"设置出错: {e}") raise def SetProgram(self, program_list: List[Program]) -> bool: """设置老化箱程序(带重试机制)""" try: # 三次重试机制 for tryout in range(1, 4): if self.WriteProgram(program_list): return True self.logger.info(f"第{tryout}次尝试写入程序失败,将在1秒后重试") time.sleep(1.0) self.logger.error("程序写入失败: 达到最大重试次数") return False except Exception as e: self.logger.error(f"设置出错: {e}") raise def RunProgram(self) -> bool: """执行程序(带重试机制)""" try: # 三次重试机制 for tryout in range(1, 4): response = str(self.send_command(self.COMMAND_EXECUTE_PROGRAM)) if response.startswith(self.OK_SIGN): self.logger.info("程序启动成功") return True self.logger.info(f"第{tryout}次尝试启动程序失败,响应: {response}") time.sleep(1.0) return False except Exception as e: self.logger.error(f"设置出错: {e}") raise def StopDevice(self) -> bool: """停止程序(带重试机制)""" try: # 三次重试机制 for tryout in range(1, 4): response = str(self.send_command(self.COMMAND_STOP_DEV)) if response and not response.startswith(self.NA_PREFIX): self.logger.info("设备已停止") return self.close_serial() self.logger.info(f"第{tryout}次尝试停止设备失败") time.sleep(1.0) self.logger.error("设备停止失败") return False except Exception as e: self.logger.error(f"设置出错: {e}") raise if __name__ == "__main__": chamber = GWSChamberCtrl(port='COM4') temp_result_data = chamber.get_temperature() print(temp_result_data) current_temp = chamber.get_current_temperature(temp_result_data) print(current_temp) humi_result_data = chamber.get_humidity() print(humi_result_data) current_humi = chamber.get_current_humidity(humi_result_data) print(current_humi) chamber.constant_mode_set(25.0, 10.0) # 示例程序设置 program_steps = [ Program(temperature=15, humidity=10, hour=2, minute=30), Program(temperature=20, humidity=15, hour=1, minute=40), Program(temperature=10, humidity=5, hour=0, minute=30) ] # 设置程序 if chamber.SetProgram(program_steps): # 运行程序 if chamber.RunProgram(): # 运行5秒后停止 time.sleep(5) chamber.StopDevice() chamber.StopDevice() chamber.close_serial()
最新发布
06-11
import serial import threading import time import numpy as np class KalmanFilter: def __init__(self, process_variance, measurement_variance, estimated_measurement_variance): self.process_variance = process_variance self.measurement_variance = measurement_variance self.estimated_measurement_variance = estimated_measurement_variance self.posteri_estimate = 0.0 self.posteri_error_estimate = 1.0 def update(self, measurement): priori_estimate = self.posteri_estimate priori_error_estimate = self.posteri_error_estimate + self.process_variance blending_factor = priori_error_estimate / (priori_error_estimate + self.measurement_variance) self.posteri_estimate = priori_estimate + blending_factor * (measurement - priori_estimate) self.posteri_error_estimate = (1 - blending_factor) * priori_error_estimate return self.posteri_estimate # 全局变量 aoa = 0.0 # 角度(Angle of Arrival) dis = -1.0 # 距离 work_mode = 0 # 工作模式(0:跟随模式) pdoa_flag = 0 # PDOA 标志 no_pdoa_count = 0 # 无 PDOA 计数 # 初始化 UART(与 UWB 传感器通信) try: ser = serial.Serial('COM3', 115200, timeout=1) # 修改为实际端口,如 COM4 except serial.SerialException as e: print(f"Error opening serial port: {e}") exit(1) def parse_aoa(data): global aoa, dis, work_mode, pdoa_flag, no_pdoa_count if data.startswith(b'MP'): parts = data.decode().strip().split(',') try: tid = int(parts[1]) x = int(parts[2]) y = int(parts[3]) range = int(parts[4]) rangnb = int(parts[5]) pdoa = float(parts[6]) # 修改为 float aoa = float(parts[7]) work_mode = int(parts[8]) dis = float(range) / 100.0 print(f"aoa={aoa}, dis={dis}") no_pdoa_count = 0 pdoa_flag = 1 except (ValueError, IndexError) as e: print(f"Error parsing data: {e}") print(f"Raw data: {data}") def uar
03-12
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using Modbus.Device; using System.IO.Ports; using Modbus.Extensions.Enron; using System.Collections; public class ModbusRTU : MonoBehaviour { // 串口设置 private SerialPort serial = new SerialPort() { PortName = "COM5", DataBits = 8, ReadBufferSize = 128, BaudRate = 9600, Parity = Parity.None, StopBits = StopBits.One, WriteTimeout = 1000, DtrEnable = false, RtsEnable = false, ReadTimeout = 1000 }; // 串口主设备 private ModbusSerialMaster serialMaster; private void Start() { try { if (!serial.IsOpen) serial.Open(); serialMaster = ModbusSerialMaster.CreateRtu(serial); // 启动后台线程读取数据和监听指令 StartCoroutine(ReadRegisters()); StartCoroutine(ListenForInstructions()); } catch (Exception ex) { Debug.LogError("Error opening serial port or creating master: " + ex.Message); } } private IEnumerator ReadRegisters() { while (true) { try { // 读取温湿度及位移数据 ushort[] temperature = serialMaster.ReadInputRegisters(0x01, 1); ushort[] humidity = serialMaster.ReadInputRegisters(0x02, 1); ushort[] displacement = serialMaster.ReadInputRegisters(0x03, 1); // 更新UI或模型状态 UpdateUIAndModel(temperature[0], humidity[0], displacement[0]); yield return new WaitForSeconds(1f); // 控制读取频率 } catch (Exception ex) { Debug.LogError("Error reading registers: " + ex.Message); } } } private IEnumerator ListenForInstructions() { while (true) { if (serial.IsOpen) { if (serial.BytesToRead > 0) { var instructionBytes = new byte[serial.BytesToRead]; serial.Read(instructionBytes, 0, instructionBytes.Length); string instruction = System.Text.Encoding.ASCII.GetString(instructionBytes).TrimEnd('\n', '\r'); switch (instruction.ToUpper()) { case "FORWARD": MoveModelForward(); break; case "BACKWARD": MoveModelBackward(); break; case "STOP": StopModel(); break; } } } yield return new WaitForEndOfFrame(); } } private void UpdateUIAndModel(float temperature, float humidity, float displacement) { // 更新UI ChartManager.Instance.UpdateTemperature(temperature); ChartManager.Instance.UpdateHumidity(humidity); ChartManager.Instance.UpdateDisplacement(displacement); // 更新模型状态 if (displacement > 0) MoveModelForward(); else if (displacement < 0) MoveModelBackward(); else StopModel(); } private void MoveModelForward() { // 移动模型向前 transform.Translate(Vector3.forward * Time.deltaTime); } private void MoveModelBackward() { // 移动模型向后 transform.Translate(Vector3.back * Time.deltaTime); } private void StopModel() { // 停止模型 // 可以在此处添加其他停止逻辑 } private void OnDestroy() { if (serial != null && serial.IsOpen) serial.Close(); } }优化以上代码
03-26
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值