_FYAW智能显示控制仪表的简单使用_串口通信
一、简介
该仪表可以实时显示位移传感器的测量值,并可设定阈值等。先谈谈简单的使用方法,通过说明书,我们可以知道长按SET键可以进入参数选择状态,按“↑”“↓”可以选择该组参数的上一个或者下一个参数。
从参数一览中可以看到有不同组的参数,当我们第一次进入参数选择状态时会进入第一组参数,可以设置不同的阈值。只不过由于是数码管,显示字母时会用一些比较奇怪的表达,比如“5”其实就是“S”,可以通过对照参数表,获取不同字母的显示。
如果想进入其他组参数,可以在第一组参数中,通过“↑”或“↓”找到最后一个oA,然后按“←”开始设置参数,当把4位数码管都设为1,即输入密码1111后,再按下SET确定,就可以解锁密码了。此时可以通过长按SET键切换到其他组参数。
更多功能可自行查看数据手册,不过要注意的是说明书中的参数并非全部与实际仪器一一对应,实际仪器有时会缺少一两个参数。
二、串口使用
串口使用的是RS485电平或者RS232,千万要注意的就是A、B的接线,不要接错。这个一般需要按照说明书的来,说明书上说“7”对应的是“B”,“8”对应的是“A”,如果仪器上贴着的标签是相反的,那么可以先按照说明书上的接法,如果不行再按照仪器上的,不要忘记接地。
接下来说说具体的串口通信,仪器默认波特率是9600,通信协议是Modbus-RTU。这里推荐使用Modbus-RTU协议。
这个通信过程并非是仪表主动不断地发送测量数据给上位机,而是需要你先发送相应命令给仪器,然后接收仪器数据。使用过程中倒是发现一些与说明书不同吻合的地方,比如读取测量值这一步,按理来说应答应如下,但实际过程中接收的是“01 04 04 42 47 3F 3F 3F 28”,即多了一个04
不过当我们需要连续读取时就会发现单次发送实在是麻烦,现在可以有下面几种方法连续发下
1,使用llcom
这个串口助手可以写lua脚本,以实现自动发送数据,并读取数据保存
chenxuuu/llcom: 🛠功能强大的串口工具。支持Lua自动化处理、串口调试、WinUSB、串口曲线、TCP测试、MQTT测试、编码转换、乱码恢复等功能 (github.com)
下面是可以发送命令并把读取数据保存起来的lua脚本。只不过lua脚本很难运行什么GUI,自然就无法显示图表
-- 发送数据中间间隔时间(单位ms) local sendDelay = 100-- 生成16进制数据“01 04 0000 0002 71CB” local usartData = "01040000000271CB" usartData=usartData:fromHex()-- 获取当前日期和时间 local function get_current_datetime()local datetime = os.date("%Y%m%d_%H%M%S")return datetime end-- 生成带有日期和时间的文件名 local function generate_filename()local datetime = get_current_datetime()return "D:/Script/python/expr_com/data_log/log_" .. datetime .. ".txt" end-- 打开文件,如果文件不存在则创建,如果存在则覆盖 local filePath = generate_filename() local file, err = io.open(filePath, "w") if not file then-- 如果文件打开失败,输出错误信息print("无法打开文件: " .. err) elseprint("文件成功打开: " .. filePath) endlocal value_str = ""-- 发送数据的函数 apiSetCb("uart", function(data)-- 写入数据value_str = data:toHex():sub(7, 14)file:write(value_str .. "\n") -- 添加换行符以便区分不同数据print(value_str) end)-- 循环发送任务 sys.taskInit(function()while true do-- 发送数据apiSendUartData(usartData)sys.wait(sendDelay)end end)-- 确保在脚本结束时关闭文件 --[[ atexit(function()if file thenfile:close()print("文件已关闭")end end) ]]
2,使用Python脚本
使用Python脚本直接打开串口,然后发送命令并读取数据,需要注意的是下面脚本里指定了一个串口,你需要打开设备管理器来找到实际串口并修改脚本里的串口为实际串口号。同时注意波特率设置。
由于仪器发送的其实是浮点数据的实际表达,所以下面脚本就自动做了这个转换
可惜的是,使用Python后,无法很好地实时更新数据到图表中,下面也就没有添加这个功能。
import serial import struct import time import os from datetime import datetime# 配置串口 ser = serial.Serial(port='COM7', # 根据实际情况修改端口号baudrate=115200, # 波特率timeout=1 # 超时设置 )# 要发送的16进制数据 send_data = bytes.fromhex('01040000000271CB')# 确保 data_log 目录存在 log_dir = 'data_log' os.makedirs(log_dir, exist_ok=True)# 获取当前日期和时间 current_time = datetime.now().strftime('%Y%m%d_%H%M%S') log_file_path = os.path.join(log_dir, f"log_{current_time}.csv")# 打开日志文件 with open(log_file_path, 'w') as log_file:log_file.write("Timestamp,Value\n") # 写入表头try:while True:# 发送16进制数据ser.write(send_data)# 从串口读取9字节的数据,并提取中间的5-8位16进制数据data = ser.read(9)[3:7]# 将16进制数据转换为32位浮点数try:float_data = struct.unpack('>f', data)[0] # '>f' 表示大端模式print(f"data: {float_data}") # 打印浮点数# 获取当前时间戳timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')# 写入日志文件log_file.write(f"{timestamp},{float_data}\n")log_file.flush() # 立即写入文件except struct.error as e:print(f"Error unpacking data: {e}")# 每100毫秒(即每秒10次)更新一次time.sleep(0.1)except KeyboardInterrupt:print("Program terminated by user")finally:# 关闭串口ser.close()
CRC校验计算
补充一点,为了可以使用其他命令,需要计算16位CRC校验值。比如下面可以数据手册上的读取测量值命令的CRC校验值“01 04 0000 0002 71CB”,其中71CB是16位校验值,在下面脚本中输入前面命令“01 04 0000 0002”即可
import crcmoddef calculate_crc16(data):# 创建一个CRC16校验对象crc16_func = crcmod.mkCrcFun(0x18005, initCrc=0xFFFF, rev=True, xorOut=0x0000)# 将16进制字符串转换为字节byte_data = bytes.fromhex(data)# 计算CRC16校验码crc_value = crc16_func(byte_data)# 交换高低字节crc_value = ((crc_value & 0xFF) << 8) | ((crc_value & 0xFF00) >> 8)return crc_value# 输入的16进制内容 hex_data = "01 04 0000 0002"# 去除空格并计算CRC16 hex_data_no_spaces = hex_data.replace(" ", "") crc16_result = calculate_crc16(hex_data_no_spaces)# 打印结果 print(f"CRC16:{crc16_result:04X}")
8位16进制字符串转为32位浮点数据
def hex_to_float(hex_str):# 将 16 进制字符串转换为 32 位无符号整数uint_value = int(hex_str, 16)# 将 32 位无符号整数转换为浮点数float_value = struct.unpack('!f', struct.pack('!I', uint_value))[0]return float_value
3,使用WPF
就功能而言,这个方法我是最满意的,可以自己定制化写一个专用的串口助手。不过它们各有缺陷,llcom虽然可以使用lua脚本做很多自动化处理,但无法显示图表。python虽然可以显示图表,但实时更新的效果并不好。使用WPF,虽然可以实现很多功能,但需要搭建Visual Studio环境,并且需要写不少代码。
由于时间限制,目前我只实现了简单的定时发送,转为浮点数据的功能。后续,我会添加显示图表的功能,记录日志的功能还没有做好,使用会出问题。并且我暂时并不打算在这上面花太多时间,所以没怎么考虑界面设计。
因此,界面很简单,使用起来也很简单。
XAML文件
<Window x:Class="expr_com.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="expr_com" Height="700" Width="1000"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto" /><!-- 可用串口 --><RowDefinition Height="Auto" /><!-- 波特率 --><RowDefinition Height="Auto" /><!-- 打开串口按钮 --><RowDefinition Height="Auto" /><!-- 发送数据 --><RowDefinition Height="Auto" /><!-- 16进制复选框 --><RowDefinition Height="Auto" /><!-- 16进制显示复选框 --><RowDefinition Height="Auto" /><!-- 单次发送和定时循环发送按钮 --><RowDefinition Height="Auto" /><!-- 周期(秒) --><RowDefinition Height="Auto" /><!-- 记录数据复选框 --><RowDefinition Height="Auto" /><!-- 处理数据复选框及参数 --><RowDefinition Height="*" /><!-- 接收数据框 --><RowDefinition Height="*" /><!-- 处理数据框 --></Grid.RowDefinitions><StackPanel Orientation="Horizontal" Grid.Row="0" Margin="10,10,10,0"><Label Content="可用串口:" Width="80" /><ComboBox Name="cmbPorts" SelectionChanged="cmbPorts_SelectionChanged" Width="150" /></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="1" Margin="10,0,10,0"><Label Content="波特率:" Width="80" /><TextBox Name="txtBaudRate" Text="115200" Width="100" /></StackPanel><Button Name="btnOpenPort" Content="打开串口" Click="btnOpenPort_Click" Width="120" Margin="10,0,10,10" Grid.Row="2" /><StackPanel Orientation="Horizontal" Grid.Row="3" Margin="10,0,10,0"><Label Content="发送数据:" Width="80" /><TextBox Name="txtSendData" Text="01040000000271CB" Width="200" /></StackPanel><CheckBox Name="chkHex" Content="16进制" Margin="10,0,10,10" Grid.Row="4" /><CheckBox Name="chkHexDisplay" Content="16进制显示" Margin="10,0,10,10" Grid.Row="5" /><StackPanel Orientation="Horizontal" Grid.Row="6" Margin="10,0,10,0"><Button Name="btnSendOnce" Content="单次发送" Click="btnSendOnce_Click" Width="120" /><Button Name="btnStartLoopSend" Content="定时循环发送" Click="btnStartLoopSend_Click" Width="120" Margin="10,0,0,0" /></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="7" Margin="10,0,10,0"><Label Content="周期(秒):" Width="80" /><TextBox Name="txtPeriod" Text="0.1" Width="50" /></StackPanel><CheckBox Name="chkLog" Content="记录数据" Margin="10,0,10,10" Grid.Row="8" /><StackPanel Orientation="Horizontal" Grid.Row="9" Margin="10,0,10,0"><CheckBox Name="chkProcessData" Content="处理数据" Margin="0,0,10,0" /><Label Content="起始位置:" Width="80" /><TextBox Name="txtStartIndex" Text="7" Width="50" Margin="0,0,10,0" /><Label Content="长度:" Width="50" /><TextBox Name="txtLength" Text="8" Width="50" /></StackPanel><TextBox Name="txtReceivedData" IsReadOnly="True" Margin="10,0,10,10" Grid.Row="10" VerticalScrollBarVisibility="Auto" /><Grid Grid.Row="11" Margin="10,0,10,10"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBox Name="txtExtractedData" IsReadOnly="True" VerticalScrollBarVisibility="Auto" Grid.Column="0" /><TextBox Name="txtFloatData" IsReadOnly="True" VerticalScrollBarVisibility="Auto" Grid.Column="1" /></Grid></Grid> </Window>
CS代码
using System; using System.IO.Ports; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.IO; using System.Timers;namespace expr_com {public partial class MainWindow : Window{private SerialPort? _serialPort; // 声明为可为 null 的类型private System.Timers.Timer? _timer; // 声告为可为 null 的类型public MainWindow(){InitializeComponent();LoadAvailablePorts();_serialPort = null; // 初始化为 null_timer = null; // 初始化为 null}private void LoadAvailablePorts(){cmbPorts.ItemsSource = SerialPort.GetPortNames();}private void cmbPorts_SelectionChanged(object sender, SelectionChangedEventArgs e){if (cmbPorts.SelectedItem != null){txtBaudRate.Focus();}}private void btnOpenPort_Click(object sender, RoutedEventArgs e){if (cmbPorts.SelectedItem == null){MessageBox.Show("请选择一个串口。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);return;}if (_serialPort == null || !_serialPort.IsOpen){try{_serialPort = new SerialPort(cmbPorts.SelectedItem.ToString(), int.Parse(txtBaudRate.Text)){ReadTimeout = 1000, // 增加读取超时时间WriteTimeout = 500,DataBits = 8,StopBits = StopBits.One,Parity = Parity.None};// 注册 DataReceived 事件_serialPort.DataReceived += SerialPort_DataReceived;_serialPort.Open();btnOpenPort.Content = "关闭串口";// 显示成功消息txtReceivedData.AppendText("← 串口已打开。" + Environment.NewLine);}catch (Exception ex){MessageBox.Show($"打开串口失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);txtReceivedData.AppendText($"← 打开串口失败: {ex.Message}" + Environment.NewLine);}}else{_serialPort.DataReceived -= SerialPort_DataReceived; // 取消注册 DataReceived 事件_serialPort.Close();btnOpenPort.Content = "打开串口";// 显示成功消息txtReceivedData.AppendText("← 串口已关闭。" + Environment.NewLine);}}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){try{string data = _serialPort.ReadExisting();if (!string.IsNullOrEmpty(data)){Dispatcher.Invoke(() =>{if (chkHexDisplay.IsChecked == true){// 将接收到的数据转换为16进制字符串byte[] bytes = Encoding.ASCII.GetBytes(data);string hexData = BitConverter.ToString(bytes).Replace("-", " ");txtReceivedData.AppendText($"→ {hexData}" + Environment.NewLine);if (chkProcessData.IsChecked == true){ProcessData(hexData);}}else{txtReceivedData.AppendText($"→ {data}" + Environment.NewLine);}// 立即滚动到底部txtReceivedData.ScrollToEnd();});}}catch (Exception ex){// 处理其他异常Dispatcher.Invoke(() =>{txtReceivedData.AppendText($"→ 读取错误: {ex.Message}" + Environment.NewLine);});}}private void LogData(string data){string logFilePath = Path.Combine("data_log", $"log_{DateTime.Now:yyyyMMdd_HHmmss}.csv");File.AppendAllText(logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss},{data}{Environment.NewLine}");}private async void btnSendOnce_Click(object sender, RoutedEventArgs e){await SendDataAsync(false);}private async void btnStartLoopSend_Click(object sender, RoutedEventArgs e){if (_timer == null || !_timer.Enabled){try{double period = double.Parse(txtPeriod.Text);_timer = new System.Timers.Timer(period * 1000); // 转换为毫秒_timer.Elapsed += OnTimedEvent;_timer.AutoReset = true;_timer.Enabled = true;btnStartLoopSend.Content = "停止循环发送";// 显示启动消息txtReceivedData.AppendText($"← 定时循环发送已启动,周期: {period} 秒。" + Environment.NewLine);}catch (Exception ex){MessageBox.Show($"设置定时发送失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);txtReceivedData.AppendText($"← 设置定时发送失败: {ex.Message}" + Environment.NewLine);}}else{_timer.Enabled = false;_timer.Dispose();_timer = null;btnStartLoopSend.Content = "定时循环发送";// 显示停止消息txtReceivedData.AppendText("← 定时循环发送已停止。" + Environment.NewLine);}}private async void OnTimedEvent(object source, ElapsedEventArgs e){try{await Dispatcher.InvokeAsync(async () =>{await SendDataAsync(true);});}catch (Exception ex){// 处理其他异常await Dispatcher.InvokeAsync(() =>{txtReceivedData.AppendText($"← 发送错误: {ex.Message}" + Environment.NewLine);});}}private async Task SendDataAsync(bool isLoop){try{if (_serialPort != null && _serialPort.IsOpen){string sendData = txtSendData.Text.Trim();if (string.IsNullOrEmpty(sendData)){throw new InvalidOperationException("发送数据不能为空。");}if (chkHex.IsChecked == true){byte[] hexData = Convert.FromHexString(sendData);_serialPort.Write(hexData, 0, hexData.Length);}else{_serialPort.WriteLine(sendData);}// 显示发送数据txtReceivedData.AppendText($"← {sendData}" + Environment.NewLine);if (chkLog.IsChecked == true){LogData(sendData);}}else{// 串口未打开,显示错误信息txtReceivedData.AppendText("← 串口未打开,无法发送数据。" + Environment.NewLine);}}catch (Exception ex){// 处理其他异常txtReceivedData.AppendText($"← 发送错误: {ex.Message}" + Environment.NewLine);}}private void ProcessData(string hexData){try{// 从文本框中获取用户输入的起始位置和长度int startIndex = int.Parse(txtStartIndex.Text) - 1; // 减1是为了适应索引从0开始int length = int.Parse(txtLength.Text);// 去除空格string hexDataWithoutSpaces = hexData.Replace(" ", "");// 检查数据长度是否足够if (hexDataWithoutSpaces.Length >= startIndex + length){// 截取指定位置和长度的数据string hexDataToProcess = hexDataWithoutSpaces.Substring(startIndex, length);// 将16进制字符串转换为字节数组byte[] bytes = Convert.FromHexString(hexDataToProcess);// 检查字节顺序if (BitConverter.IsLittleEndian){// 如果系统是小端序,而数据是大端序,则需要反转字节顺序Array.Reverse(bytes);}// 将字节数组转换为浮点数float floatValue = BitConverter.ToSingle(bytes, 0);// 追加结果txtExtractedData.AppendText($"{hexDataToProcess}" + Environment.NewLine);txtFloatData.AppendText($"{floatValue}" + Environment.NewLine);// 立即滚动到底部txtExtractedData.ScrollToEnd();txtFloatData.ScrollToEnd();}else{txtExtractedData.AppendText("数据长度不足,无法处理。" + Environment.NewLine);}}catch (FormatException ex){txtExtractedData.AppendText($"格式错误: {ex.Message}" + Environment.NewLine);}}} }
实际效果:
单次发送
循环发送
相关文章:

_FYAW智能显示控制仪表的简单使用_串口通信
一、简介 该仪表可以实时显示位移传感器的测量值,并可设定阈值等。先谈谈简单的使用方法,通过说明书,我们可以知道长按SET键可以进入参数选择状态,按“↑”“↓”可以选择该组参数的上一个或者下一个参数。 从参数一览中可以看到有…...

激光雷达定位初始化的另外一个方案 通过键盘按键移动当前位姿 (附python代码)
通常使用的是通过在 rviz 中点选指定初始化位置和方向来完成点云的初始化匹配。 但是这种粗略的初始化方法有时候可能不成功,因此需要使用准确的初始化方法,以更好的初始值进行无损检测配准。 为了提供更好的匹配初始值,我使用 Python 脚本获取键盘输入,并不断调整这个匹配…...

从0-1逐步搭建一个前端脚手架工具并发布到npm
前言 vue-cli 和 create-react-app 等 cli 脚手架工具用于快速搭建应用,无需手动配置复杂的构建环境。本文介绍如何使用 rollup 搭建一个脚手架工具。 脚手架工具的工作流程简言为:提供远端仓库各种模版 > 用户通过命令选择模版 > 拉取仓库代码 …...

河道水位流量一体化自动监测系统:航运安全的护航使者
在广袤的水域世界中,航运安全始终是至关重要的课题。而河道水位流量一体化自动监测系统的出现,如同一位强大的护航使者,为航运事业的稳定发展提供了坚实的保障。 水位传感器:负责实时监测河道的水位变化。这些传感器通常采用先进的…...

维护在线重做日志
学习目标 解释在线重做日志文件的目的概述在线重做日志文件的结构控制日志开关和检查点多路复用和维护在线重做日志文件使用OMF管理在线重做日志文件获取在线重做日志文件信息 在线重做日志文件提供了在数据库发生故障时重做事务的方法。 每个事务都同步写入重做日志缓冲区&a…...

ASCB1系列APP操控末端回路智能微断 物联网断路器 远程控制开关 学校、工厂、农场、商业大楼等可用
安科瑞戴婷 Acrel-Fanny ASCB1系列智能微型断路器是安科瑞电气股份有限公司全新推出的智慧用电产品,产品由智能微型断路器与智能网关两部分组成,可用于对用电线路的关键电气因素,如电压、电流、功率、温度、漏电、能耗等进行实时监测&#x…...
Python入门(10)--面向对象进阶
Python面向对象进阶 🚀 1. 继承与多态 🔄 1.1 继承基础 class Animal:def __init__(self, name, age):self.name nameself.age agedef speak(self):passdef describe(self):return f"{self.name} is {self.age} years old"class Dog(Anim…...
Makefile 之 自动化变量
作用范围只在这条规则以及连带规则中,所以其值也只在作用范围内有效。而不会影响规则链以外的全局变量的值。 "$" 表示目标的集合,就像一个数组,"$"依次取出目标,并执于命令。 "$<"和"$&qu…...

鸿蒙开发:ForEach中为什么键值生成函数很重要
前言 在列表组件使用的时候,如List、Grid、WaterFlow等,循环渲染时都会使用到ForEach或者LazyForEach,当然了,也有单独使用的场景,如下,一个很简单的列表组件使用,这种使用方式,在官…...

沃丰科技智能外呼机器人:超越人工,重塑外呼体验
随着科技的不断发展,人工智能已经逐渐渗透到各行各业,其中智能外呼机器人的出现,更是给企业带来了全新的客户体验。与传统的人工外呼相比,智能外呼机器人具有更高的效率、更低的成本以及更好的用户体验等优势。 优势一࿱…...
百度飞浆:paddle 线性回归模型
学习引用 参考视频: https://www.bilibili.com/video/BV1oRtkeVEVx?spm_id_from333.788.player.switch&vd_sourcec7739de98d044e74cdc74d6e772bed5f&p2 这段代码使用PaddlePaddle深度学习框架来实现一个简单的线性回归模型,旨在从给定的出租车…...

【JavaSE】【网络编程】UDP数据报套接字编程
目录 一、网络编程简介二、Socket套接字三、TCP/UDP简介3.1 有连接 vs 无连接3.2 可靠传输 vs 不可靠传输3.3 面向字节流 vs 面向数据报3.4 双向工 vs 单行工 四、UDP数据报套接字编程4.1 API介绍4.1.1 DatagramSocket类4.1.1.1 构造方法4.1.1.2 主要方法 4.1.2 DatagramPocket…...

45.坑王驾到第九期:Mac安装typescript后tsc命令无效的问题
点赞收藏加关注,你也能主打别墅! 一、问题描述 Mac上终端运行如下命令: sudo npm install typescript -g //全局安装ts提示成功安装后,我测试tsc -v这个命令时出现如下错误: 也就是说找不到 tsc 命令。 二、解决方…...

20241120-Milvus向量数据库快速体验
目录 20241120-Milvus向量数据库快速体验Milvus 向量数据库pymilvus内嵌向量数据库模式设置向量数据库创建 Collections准备数据用向量表示文本插入数据 语义搜索向量搜索带元数据过滤的向量搜索查询通过主键搜索 删除实体加载现有数据删除 Collections了解更多 个人主页: 【⭐…...

【Golang】——Gin 框架中间件详解:从基础到实战
中间件是 Web 应用开发中常见的功能模块,Gin 框架支持自定义和使用内置的中间件,让你在请求到达路由处理函数前进行一系列预处理操作。这篇博客将涵盖中间件的概念、内置中间件的用法、如何编写自定义中间件,以及在实际应用中的一些最佳实践。…...

量子计算来袭:如何保护未来的数字世界
目录 前言 一、量子计算安全的学习方向 1. 量子物理学基础 2. 量子计算原理与技术 3. 传统网络安全知识 4. 量子密码学 5. 量子计算安全政策与法规 二、量子计算的漏洞风险 1. 加密算法被破解风险 2. 区块链安全风险 3. 量子密钥分发风险 4. 量子计算系统自身风险 …...

VMware虚拟机(Ubuntu或centOS)共享宿主机网络资源
VMware虚拟机(Ubuntu或centOS)共享宿主机网络资源 由于需要在 Linux 环境下进行一些测试工作,于是决定使用 VMware 虚拟化软件来安装 Ubuntu 24.04 .1操作系统。考虑到测试过程中需要访问 Github ,要使用Docker拉去镜像等外部网络资源,因此产…...

光伏电站仿真系统的作用
光伏仿真系统有多方面的重要作用,不仅对前期的项目设计评估还是后期的运维效验都有非常重要的作用。 1、优化系统设计 通过输入不同的光伏组件参数、布局方案以及气象条件等,模拟各种设计场景下光伏电站的性能表现。例如,可以比较不同类型光…...
Golang文件操作
写文件 &emsp; os模块可以创建文件,使用fmt可以写入文件。如以下例子: package mainimport ("fmt""os" )func main() {// 学习 golang的文件操作file, err : os.Create("test.txt")if err ! nil {fmt.P…...

爬虫开发工具与环境搭建——使用Postman和浏览器开发者工具
第三节:使用Postman和浏览器开发者工具 在网络爬虫开发过程中,我们经常需要对HTTP请求进行测试、分析和调试。Postman和浏览器开发者工具(特别是Network面板和Console面板)是两种最常用的工具,能够帮助开发者有效地捕…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...