How to write to holding registers in pymodbus? - pymodbus

I want to write to the holding registers an actuator of mine has, but I've only recently started using pymodbus and I'm a little uncertain about some of its commands. As far as I've understand the primary write command looks like this:
write_register(address, value, **kwargs)
But I'm uncertain about how I "define" which kind of register I write too. Unlike other modbus libraries I've used, in pymodbus I can't define which kind of register I write too. As far as I understand of modbus there's coils, input registers and holding registers. I've read that you can't write to input registers, but how can I be certain I write to holding registers? If I write 1 in address in the write_register will that always be a holding register with that address?
Thank you in advance.

You need to know a little bit more about your actuator. Do you have a datasheet about it? If yes, you need to find a map registers where all the addresses are given for registers where the actuator's information are stored. Here an example where you can find this kind of registers map : SIMEAS Pxxx Com-Modbus Datasheet.
Be careful, sometimes you need to add or subtrace 1 to your register address because the guys who implement this did in this way. Read your datasheet carefully.
So if you need to write something in a particular register, you need the correct address of the register, the value you want to write in the correct format, and the client of the library ModbusClient.
You should have something like this :
client = ModbusClient(host='YOUR_IP_ADRESS', port=xxx)
client.connect()
client.write_register(REGISTER_ADRESS, PAYLOAD, UNIT)
Hope this will help a little. You can also go further by reading the Pymodbus documentation.

Related

How do I add a missing peripheral register to a STM32 MCU model in Renode?

I am trying out this MCU / SoC emulator, Renode.
I loaded their existing model template under platforms/cpus/stm32l072.repl, which just includes the repl file for stm32l071 and adds one little thing.
When I then load & run a program binary built with STM32CubeIDE and ST's LL library, and the code hits the initial function of SystemClock_Config(), where the Flash:ACR register is being probed in a loop, to observe an expected change in value, it gets stuck there, as the Renode Monitor window is outputting:
[WARNING] sysbus: Read from an unimplemented register Flash:ACR (0x40022000), returning a value from SVD: 0x0
This seems to be expected, not all existing templates model nearly everything out of the box. I also found that the stm32L071 model is missing some of the USARTs and NVIC channels. I saw how, probably, the latter might be added, but there seems to be not a single among the default models defining that Flash:ACR register that I could use as example.
How would one add such a missing register for this particular MCU model?
Note1: For this test, I'm using a STM32 firmware binary which works as intended on actual hardware, e.g. a devboard for this MCU.
Note2:
The stated advantage of Renode over QEMU, which does apparently not emulate peripherals, is also allowing to stick together a more complex system, out of mocked external e.g. I2C and other devices (apparently C# modules, not yet looked into it).
They say "use the same binary as on the real system".
Which is my reason for trying this out - sounds like a lot of potential for implementing systems where the hardware is not yet fully available, and also automatted testing.
So the obvious thing, commenting out a lot of parts in init code, to only test some hardware-independent code while sidestepping such issues, would defeat the purpose here.
If you want to just provide the ACR register for the flash to pass your init, use a tag.
You can either provide it via REPL (recommended, like here https://github.com/renode/renode/blob/master/platforms/cpus/stm32l071.repl#L175) or via RESC.
Assuming that your software would like to read value 0xDEADBEEF. In the repl you'd use:
sysbus:
init:
Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF
In the resc or in the Monitor it would be just:
sysbus Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF
If you want more complex logic, you can use a Python peripheral, as described in the docs (https://renode.readthedocs.io/en/latest/basic/using-python.html#python-peripherals-in-a-platform-description):
flash: Python.PythonPeripheral # sysbus 0x40022000
size: 0x1000
initable: false
filename: "script_with_complex_python_logic.py"
```
If you really need advanced implementation, then you need to create a complete C# model.
As you correctly mentioned, we do not want you to modify your binary. But we're ok with mocking some parts we're not interested in for a particular use case if the software passes with these mocks.
Disclaimer: I'm one of the Renode developers.

Libnodave on value changed

I am using libnodave 0.8.4.4 library to connect to a S7 PLC and what I would like to know if how can I detect if a bit (e.g. DB100.DBX8.0) in PLC DB changes its value. What I did is to read this bit within a while loop but I would like to create an event on value changed on this bit and launch a task when it happens.
There is no default event available with libnodave or any other libraries like S7.net.
Either you need to use OPCor write your own function which will read the set of bits set on time and notify to the main program.

OracleSolaris 11.2 -- is /usr/kernel/drv/driver.conf required for PCI?

I'm implementing a small PCI driver for academic purposes, and one thing I'm not clear about if we actually have to provide driver.conf? Different materials which I read (including http://blog.csdn.net/hotsolaris/article/details/1763716), say that for PCI the driver config file is optional, however in my case it seems that pci_config_setup() is successful only with driver.conf provided:
name="mydrv" parent="/pci#0,0/pci8086,2e11"
Then I do:
% add_drv -i 'pciXXXX,YY' mydrv
and it adds in the system with no warning or error messages.
So I assume that some properties of a PCI device can't be derived automatically by the system, e.g. parent bus?
I would appreciate if anybody could shed some light on this. Thanks.
If you look at a random selection of very small files under /kernel/drv for actual physical hardware, you'll see that they almost always only contain the line
ddi_forceattach=1;
Pseudo drivers will have a driver.conf(4) file which reflects their parentage in the system. I really recommend reading that manpage, it goes into good detail about what's required here.

Force writing only-read register #Modbus

I was wondering,
Is there anyway to force writing on a 'Read-Only' Modbus Register?
Does defining a Register as a 'Read-Only' is secure enough or can be bypassed??
Thanks for the answers!
The correct way to define a "read-only" analog variable in Modbus is to map it as an input register. There is no function code defined in Modbus to write to an input register.
For historical reasons, several vendors maps all their variables as holding registers, which are theoretically read/write, i.e, there's a Write Multiple Registers function. Whenever they map a read only variable as a holding register, they must assert that the write functions fail. However, there's no standard exception code for this, as a holding register should be read/write. This is only one of Modbus' idiosyncrasies.
Getting back to your question, if you map your variable as an input register, you can be sure that the protocol will not allow a master to write to it. If, for interoperability issues you map it as a holding register, the protocol will allow the master to use a write funcion to change its value, and it is up to you to block in your device implementation.

Specman e vr_ad: How to use read_reg_field?

in UVM e Reference document is written:
You can call read_reg_field or write_reg_field for registers whose fields
are defined as single_field_access (see “vr_ad_port_unit Syntax and Examples”).
...
For example:
write_reg_fields tx_mode_reg {.resv = 4; .dest = 2};
But there is no example for using read_reg_field...
Could you please explain how should it be used?
(I've tried the next code, but it gives compilation error:
some_var = read_reg_field my_reg_file.my_reg {.my_reg_field} )
Thank you for your help.
As far as I know there is no read_reg_fieds macro. If you want to do a read to a register and then save the value of a certain field, do this:
read_reg my_reg;
value = my_reg.my_reg_field;
Normally, when you read register, you read them completely. Reading only individual fields makes sense if your bus protocol allows narrow transfers (i.e. your data width is 32 bits, but you can do 16 bit transfers on it). I haven't seen such a thing implemented in vr_ad (could be there and I just don't know of it), but UVM RAL (the SystemVerilog register package) supports it.
Long story short, if you just care about getting your data from your DUT, using read_reg is enough.
When the Design Under Test is implemented in verilog or vhdl - you can read the register as a whole, you cannot "read just some of its fields".
A register is at a specific address, reading this register -> read from this address.
The quote of the spec about fields access is when the DUT is a SystemC model.
Connecting to SC models is done using ports. If the model defines a port for each field - you can read a field.