项目进度:
完成基本参数和运行模式页面的代码,可获取基本参数字典,还没有获取运行模式字典模块。
目录
项目进度:
问题1
问题描述
原因分析
解决方案
问题2
问题描述
原因分析
解决方案
问题3
问题描述
原因分析
解决方案
问题4
问题描述
原因分析
解决方案
问题5
问题描述
原因分析
解决方案
问题6
问题描述
原因分析
解决方案
问题7
问题描述
原因分析
解决方案
问题8
问题描述
原因分析
解决方案
问题1
问题描述
十进制数-10000,转十六进制是0xFFFFD8F0,再转十进制时,数据变成4294957296,再转十六进制没问题,还是0xFFFFD8F0。
原因分析
十进制与十六进制转换函数中,未明确负数转换机制。
python 是将输入的数分割成符号和数值两部分,那就是如电脑计算器算出来的一样:
不会判断符号位,就导致直接转换十六进制数的现象。
解决方案
使用 binascii 和 struct 包进行转换, 参考:http://t.csdn.cn/zvRHN
主要参考的是这块指导,但链接原文说的不太对:
2.十六进制还原为负数
先提取为十六进制的字符串,并逆置
neghex_s = hex(neghex)[2:-1] = 'ffff0520'
neghex_s=neghex_s[::-1] = '0250ffff'
使用binascii.unhexlify进行去十六进制化
neghex_pack=binascii.unhexlify(neghex_s)='x02Pxffxff'
再利用struct.unpack进行解析
neg=struct.unpack('i', neghex_pack)=(-45054,)
那么neg[0]就是neghex还原的负数
应该是把字符串 'ffff0520' 改为 '2005ffff',再按程序进行去十六进制化和解析,得到的才是我想要的负数。
更正后代码如下:
def value_translate(value, num):
if value[0:2] == '0x': # value是十六进制
if num == 'dec': # 十进制显示
value = value[2:]
if len(value) < 5: # 如果数据是0x1,则在前面补0,成为0x00000001
while len(value) < 8:
value = '0' + value
else:
pass
value = value[6:8] + value[4:6] + value[2:4] + value[0:2]
value_pack = binascii.unhexlify(value)
trans_value = struct.unpack('i', value_pack)
value = trans_value[0]
print('当前为十六进制,换算后重新显示', value)
......
问题2 问题描述
源地址表中有区分子地址的参数,查找通讯字典对应的地址不正确。举例:
参数:目标位置1,CAN地址:0x3547,子地址:0x01
参数:目标位置2,CAN地址:0x3547,子地址:0x02
查询Modbus通讯地址应为:目标位置1:0x69,目标位置2:0x6B
实际为:目标位置1:0xF0D6,目标位置2:0xF0D8
原因分析查询通讯字典表时未加入对子地址的数据筛选。
实际是筛选子地址前,会先定位地址,然后应该是以定位地址得到的数据中再次筛选子地址,而当前是以原地址表所有数据筛选子地址了。
解决方案# 查询Index对应的其他信息
def search(self, index, subindex):
search_dic = {}
i = self.mdic.loc[self.mdic['Od_Index'].isin([index])]
print('ModbusDict')
print(i)
# 判断找地址表,找到则返回字典,没找到则返回0
if i.size > 0:
if len(i) > 1: # 有子地址区分
print('len(i) > 1')
# 错误语句:i = self.mdic.loc[self.mdic['Od_Subindex_hex'].isin([subindex])]
# 更正:
i = i.loc[self.mdic['Od_Subindex_hex'].isin([subindex])]
print(i)
else:
pass
问题3 问题描述
Modbus通讯地址不需转换长度,CANOpen地址和子地址不需转换十进制。
原因分析进制转换中没对通讯做区分。
解决方案修改后代码:
if self.B_type.currentIndex() == 0: # Modbus通讯,地址由十进制变十六进制
trans_index = modbus_index(index, num)
print('地址显示:', trans_index)
self.para_index.setItem(1, column - 3, QtWidgets.QTableWidgetItem(trans_index))
else: # Modbus通讯地址不需转换长度,CANOpen地址和子地址不需转换十进制
pass
问题4 问题描述
多段参数表中的运行模式下拉框没有显示对应行列的索引地址。
原因分析该部分还未完成。
解决方案2022-6-23 已完成
问题5 问题描述
多段参数表中如有空白的参数,点击时程序退出,无法显示对应的地址。
原因分析我获取当前点击的单元格用的是QTableWidget.currentItem(),而QTableWidget只有输入数值,才会产生item,因此空白单元格的currentItem()返回是None,而我显示是直接用的currentItem().text(),就会报错None没有text属性。
解决方案更改为QTableWidget.currentIndex(),无论是否有输入数值,都可以用currentIndex().data()获取空白的内容或输入的数值。
问题6 问题描述
连续点击多段参数表中的参数,显示的地址表中最后一列的标题不对。
原因分析从列0往列1,列2...删除,要注意每删除一次,原列表的非0索引值会自动递减 1,因此每次都少一删除一列。
# 复原地址表
if self.para_index.columnCount() > 3:
for j in range(0, self.para_index.columnCount() - 2): # 只保留3列
self.para_index.removeColumn(j)
else:
pass
解决方案
更改为从后面往前面删除:
# 复原地址表
if self.para_index.columnCount() > 3:
for j in range(self.para_index.columnCount() - 4, -1, -1): # 只保留3列
self.para_index.removeColumn(j)
else:
pass
问题7 问题描述
多段参数表的运行参数1和2的当前取值,需要转换速度单位。
原因分析该部分还未完成。
解决方案2022-6-23已完成
问题8 问题描述
由多段参数表查询地址后,切换回其他模式,地址表的列数显示不对。
原因分析和问题6相同
解决方案参考问题6
全部解决时间:2022-6-23



