Pymodbus:如何读取该输入寄存器的各个位?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pymodbus:如何读取该输入寄存器的各个位?相关的知识,希望对你有一定的参考价值。

我有一个太阳能项目和实时监控器,它使用EpSolar Tracer充电控制器和Raspberry Pi通过MODBUS读取能量数据。

当它们是简单的整数时,我很容易读取输入寄存器,就像这样 -

# Request the range of registers that hold the solar/battery realtime data (3100 - 3105)
result = client.read_input_registers(0x3100,6,unit=1)

# Solar voltage is register 3100, divide by 100
sV = float(result.registers[0] / 100.0)

..但是我无法理解我如何读取一个输入寄存器,其中每个单独的位代表不同的东西。特别是,我想读一个包含12条不同信息的“收费状态”寄存器 -

当我读到这个寄存器(0x3201)时,我得到的全部是数字7.如何读取该寄存器中12个不同的数据?我想也许7是0000000000000111的十进制表示 - 但我不认为这是正确的。

任何有关这方面的帮助将不胜感激!

马特

答案

你走在正确的轨道上。这些比特很容易搞清楚。这是如何做:

16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
                                           1  1  1

顶行是位位置,底线是值7 ...让我们说你对第2位感兴趣,第3位是从右边开始。让我们通过获取1并将其移动到n时间来为该位制作一个掩码,其中n是位位置。所以我们想要改变它2次:

int mask =(1 << 2);

这将产生:

16 15 14 13 12 11 10 09 09 07 06 05 04 03 02 01 00
                                           1  0  0

现在我们所做的就是确定第二位是否设置为AND的值和掩码

16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
                                           1  1  1   value
                                           1  0  0   mask
--------------------------------------------------
                                           1  0  0   ANDed result

所以,在C:

int value = 7;  // or any 16-bit value
int mask = (1 << 2);  // == 4

if ((value & (1 << 2)) == mask)
    // bit is set
else
    // bit is not set

现在,有时你想要提取多个位。这是一个如何提取两位组合的示例。首先让我们规定两位11是值3(一个1和一个2)。所以现在要做一个类似的过程从同一个值中提取两个比特(7)。

16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1

现在我们用3而不是1掩盖:

int mask =(3 << 2);

这将产生:

16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
 0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  0  0

现在我们所做的就是确定第二位是否设置为AND的值和掩码

16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1   value
 0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  0  0   mask
--------------------------------------------------
                                        0  1  0  0   ANDed result

但文档可能会说比特:3-2是“状态x”。价值观 -

00 - a
01 - b
02 - c
03 - d

所以现在我们必须从上面的ANDed结果中获取最终值0100,并将它向右移动两个以获得这些可能的值:

result = (old_result >> 2);
0100 >> 2 == 01 

由于结果是01,十进制1,十六进制1,那么结果是从上面的b

编辑:

现在在python中进行最后的计算:

>>> value = 0x0007
>>> mask = (3 << 2)
>>> result = value & mask
>>> print (result)
4
>>> shifted_result = result >> 2
>>> print (shifted_result)
1

同样的结果,位3-2等于1,这意味着(根据您的数据表)诊断结果是:

位0:“运行”位1:“故障”位3-2:“浮动”

以上是关于Pymodbus:如何读取该输入寄存器的各个位?的主要内容,如果未能解决你的问题,请参考以下文章

Pymodbus 读取和解码寄存器值

如何让 pymodbus 与 PLC 正确通信?

将值分配给 TCP 服务器寄存器的 pymodbus 语法是啥?

Pymodbus/Twisted 异步客户端重新连接

如何在 PYMODBUS(Modicon?)中塑造一个 CALL

具有多个从设备上下文的 pymodbus Modbus 服务器实现 - 写入寄存器会覆盖所有从设备