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 - но я не думаю, что это может быть правильно.
Любая помощь в этом будет оценена!
Matt
1 ответ
Вы на правильном пути. И эти биты легко достать. Вот как:
16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
1 1 1
Верхняя строка - это позиция бита, а нижняя строка - это значение 7... допустим, вас интересует бит 2, третий справа. Давайте сделаем немного маски для этого, взяв 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 это "статус х". ценности -
00 - a
01 - b
02 - c
03 - d
Итак, теперь мы должны взять наше окончательное значение, 0100 из AND
приведите приведенный выше результат и сдвиньте его на два вправо, чтобы получить следующие возможные значения:
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: "поплавок"