Problem reading registers from Carlo Gavazzi EM24-DIN.AV5 using Python / ModBUS - modbus

Dears,
I have a Carlo Gavazzi Energy Meter EM24-DIN.AV5 and I'm connecting it with Raspberry PI using USB/RS485 converter (zk-u485). The A/B/GND ports of USB-RS485 are wired with ports 41/42/43 of the device.
The device have a Joystick to configure the Serial Baudrate and the ModBus address (in my case they are 9600 and 3).
I used this sample of code to read some registers, but always receiving Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received) D
#!/usr/bin/env python
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=3, stopbits = 1, bytesize = 8, parity='N', baudrate= 9600)
val = client.connect()
if not val:
print("******** Connection error *************")
while True:
# rr = client.read_input_registers(address=37, count=2, unit=3);
rr = client.read_input_registers(2,2,unit=3)
print( rr);
Follwing the full debug log:
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x3 0x4 0x0 0x2 0x0 0x2 0xd1 0xe9
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Transaction failed. (Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received))
DEBUG:pymodbus.framer.rtu_framer:Frame - [] not ready
DEBUG:pymodbus.transaction:Getting transaction 3
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)
DEBUG:pymodbus.transaction:Current transaction state - TRANSACTION_COMPLETE
DEBUG:pymodbus.transaction:Running transaction 2
DEBUG:pymodbus.transaction:SEND: 0x3 0x4 0x0 0x2 0x0 0x2 0xd1 0xe9
DEBUG:pymodbus.framer.rtu_framer:Changing state to IDLE - Last Frame End - None, Current Time stamp - 1596433492.94
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Incomplete message received, Expected 9 bytes Recieved 0 bytes !!!!
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV:
DEBUG:pymodbus.framer.rtu_framer:Frame - [] not ready
DEBUG:pymodbus.transaction:Getting transaction 3
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Modbus Error: [Input/Output] No Response received from the remote unit/Unable to decode response
DEBUG:pymodbus.transaction:Current transaction state - TRANSACTION_COMPLETE
DEBUG:pymodbus.transaction:Running transaction 3
DEBUG:pymodbus.transaction:SEND: 0x3 0x4 0x0 0x2 0x0 0x2 0xd1 0xe9
DEBUG:pymodbus.framer.rtu_framer:Changing state to IDLE - Last Frame End - 1596433495.95, Current Time stamp - 1596433495.95
DEBUG:pymodbus.framer.rtu_framer:Waiting for 3.5 char before next send - 4.01 ms
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
Following the ModBus protocol documentation:
https://www.ccontrols.com/support/dp/CarloGavazziEM24.pdf
ModBus Addresses
Your help is very much appreciated.

Related

In device tree, can't understand 'ranges' property of PCIe root complex node

For example in linux-5.15.68's arch/arm64/boot/dts/ti/k3-am64-main.dtsi,
&cbass_main {
... skip ...
pcie0_rc: pcie#f102000 {
compatible = "ti,am64-pcie-host", "ti,j721e-pcie-host";
reg = <0x00 0x0f102000 0x00 0x1000>,
<0x00 0x0f100000 0x00 0x400>,
<0x00 0x0d000000 0x00 0x00800000>,
<0x00 0x68000000 0x00 0x00001000>;
reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
... skip ...
#address-cells = <3>;
#size-cells = <2>;
...skip ...
msi-map = <0x0 &gic_its 0x0 0x10000>;
ranges = <0x01000000 0x00 0x68001000 0x00 0x68001000 0x00 0x0010000>,
<0x02000000 0x00 0x68011000 0x00 0x68011000 0x00 0x7fef000>;
dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x00000010 0x0>;
};
};
the 'ranges' property says
IO space starting at address 0x68001000 with size 64KiB is mapped to the parent bus address 0x68001000.
a 32 bit memory address space starting with address 0x68011000 and size 0x7fef000 is mapped to parent bus address 0x68011000.
The device tree document says these addresses are all physical.
What I can't understand is :
I know the BIOS will set the BAR addresses during the enumeration process. This is allocating the endpoint's function to a certain PCIe bus address and I guess setting BAR can be done without this 'ranges' information(it will assign free address range for that device according to the device's need). By the time linux kernel later reads this 'ranges' property, the BIOS (or bootloader) has already assigned different PCIe address to that device. Then, how is this 'ranges' property used by the kernel?

Reading/Writing to LSM6DSOX via SPI from Raspberry Pi

I'm having trouble reading and writing to my Adafruit LSM6DSOX IMU from my Raspberry Pi 4 running Ubuntu 20.04. I need to do it via SPI since I require the bandwidth, but I can only seem to read the WHO_AM_I register successfully. Reading/writing to any other register only returns 0x00. I have verified that I can read data off the IMU from an Arduino via SPI, but if I try to read a register other than 0x0F (the IMU_ID) I get 0x0 as a response. Any insight/ideas what could be causing this would be greatly appreciated!
EDIT: It turns out I can read the following registers:
0x0f : 0x6c
0x13 : 0x1c
0x33 : 0x1c
0x53 : 0x1c
0x73 : 0x1c
These are all random registers however, and the value 0x1C doesn't seem to correspond with anything.
This is my main.py:
import LSM6DSOX
def main():
imu=LSM6DSOX.LSM6DSOX()
imu.initSPI()
whoamI=imu.read_reg(0x0F)
while(whoamI != imu.LSM6DSOX_ID):
imu.ms_sleep(200)
print('searching for IMU')
whoamI=imu.get_id()
print(hex(whoamI))
print('found lsm6dsox IMU')
imu.spi.close()
imu.spi = None
if __name__=="__main__":
main()
This is an excerpt from my LSM6DSOX.py:
def initSPI(self):
# Setup communication SPI
self.spi = spidev.SpiDev()
self.spi.open(0, 0)
self.spi.mode=0b11 #mode 3, (mode 0 is also fine)
self.spi.max_speed_hz = 500000
return self.spi
def read_reg(self, reg, len=1):
# Set up message
buf = bytearray(len+1)
buf[0] = 0b10000000 | reg # MSB bit must be 1 to indicate a read operation. this is OR'd with the register address you want to read
resp =self.spi.xfer2(buf) #send (and recieve) data to the imu
if len==1:
return resp[1]
else:
return resp[1:] #display recieved data
def write_reg(self, reg, data, len=1):
# Set up message
buf = bytearray(len+1)
buf[0] = 0b00000000 | reg # MSB bit must be 0 to indicate a read operation. this is OR'd with the register address you want to read
buf[1:] =bytes(data)
resp =self.spi.xfer2(buf) #send (and recieve) data to the imu
return resp[1:] #display recieved data

Elixir socket duplicate STX and ETX in response

I have socket server with this method:
#impl true
def handle_call({:tcp, socket, packet}, state) do
Logger.info("Received packet: \x02#{packet}\x03 and send response")
{:reply, {:ok, packet}, state}
end
I wrote script in python that send "\x02Test\x03" to socket:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", port))
s.send("\x02Test\x03".encode())
print(s.recv(1024))
But the response printed by python is b'\x02\x02Test\x03\x03'
What does handle_call() have to do with gen_tcp?
gen_tcp can be configured to read from a socket and send() messages to whatever process called :gen_tcp.accept(), the so called controlling process, which can be a gen_server; but a gen_server handles messages sent to its mailbox with handle_info()--not handle_call(). handle_call() handles messages sent by :gen_server.call().
Here's an example:
defmodule TcpServer do
use GenServer
require Logger
def start_link() do
ip = Application.get_env :gen_tcp, :ip, {127,0,0,1}
port = Application.get_env :gen_tcp, :port, 6666
IO.puts "gen_tcp is listening on port: #{port}"
GenServer.start_link(__MODULE__, {ip, port},[])
end
def init({ip, port}) do
{:ok, listen_socket}= :gen_tcp.listen(
port,
[:binary, {:packet,0}, {:active,true}, {:ip,ip}]
)
{:ok, socket } = :gen_tcp.accept listen_socket
{:ok, %{ip: ip, port: port, socket: socket} }
end
def handle_call({:tcp, _socket, packet}, state) do
Logger.info("handle_call(): Received packet: #{inspect packet}")
{:reply, {:ok, packet}, state}
end
def handle_info({:tcp,socket,packet},state) do
Logger.info "handle_info(:tcp, ...): incoming packet: #{inspect packet}"
:gen_tcp.send(socket, "****#{packet}*****")
{:noreply,state}
end
def handle_info({:tcp_closed, _socket}, state) do
Logger.info("handle_info({:tcp_closed, ...): Client closed socket.")
{:noreply, state}
end
def handle_info({:tcp_error, socket, reason}, state) do
Logger.info("Connection closed due to #{reason}: #{socket}")
{:noreply,state}
end
end
To start the server:
~/elixir_programs/tcp_server$ iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> TcpServer.start_link()
gen_tcp is listening on port: 6666
In another terminal window:
~/python_programs$ cat 5.py
import socket
port = 6666
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", port))
s.send("\x02Test\x03".encode())
print(s.recv(1024))
~/python_programs$ p36 5.py
b'****\x02Test\x03*****'
~/python_programs$
As you can see, there was no duplication of the \x02 and \x03 characters.
Back in the server window:
{:ok, #PID<0.123.0>}
iex(2)>
21:54:18.363 [info] handle_info(:tcp, ...): incoming packet: <<2, 84, 101, 115, 116, 3>>
21:54:18.369 [info] handle_info({:tcp_closed, ...): Client closed socket.
Do you have another process that is the controlling process and is calling :gen_server.call({:tcp, socket, packet})?
By the way, in this code:
def handle_info({:tcp,socket,packet},state) do
packet may be the whole packet, 1/2 the packet or 1/10 of the packet. That's the way sockets work. The config option {packet, 0} tells gen_tcp that there is no length header (0 bytes) on the front of the packet, while {packet, 1|2|4} tells gen_tcp that the length of the packet is contained in the first byte, the first 2 bytes, or the first 4 bytes respectively. That way gen_tcp can read the first 1|2|4 bytes to get the packet length, say L, then keep reading from the socket until it has received L bytes. Then gen_tcp packages up the pieces into one message, and sends the whole message to the gen_server. On the other hand, when you specify {packet, 0}, you are telling gen_tcp that the packet has no length header; and because a socket splits up a single packet into an indeterminate number of chunks, gen_tcp has no idea where the end of the packet is, so gen_tcp's only option is to read a chunk from the socket and send the chunk to the gen_server; then read another chunk and send the chunk to the gen_server, etc., etc. That means the gen_server has to figure out where the end of the packet is.
Therefore, your server and your client have to agree on a protocol to signal the end of a packet; and handle_info(:tcp, ...) will have to store the pieces of the packet in the state (or in a db) until it has read all the chunks that make up a packet.
One protocol that you can use to signal the end of the packet is: the client closes the socket. In that case,
def handle_info({:tcp_closed, _socket}, state)
will be called, and inside that function clause you can assemble the chunks stored in state (or in a db) into a complete message, then do whatever is necessary, e.g. send the message back to the client.
If you use STX and ETX as your begin message, end message protocol, then handle_info(:tcp, ...) will still have to look for the STX character to signal that it should start storing chunks in state, and when handle_info(:tcp, ...) finds a chunk with an ETX character in it, then you have to assemble the entire message.

Data transmission Pi/MCP3008

I have a question regarding data transmisison from a Raspberry Pi to a mcp3008. It is just a theoretical one. When they exchange the bytes does the master send 1 byte and receives 1 byte. Then sends the 2nd byte and receives 2nd byte.. OR does the master send 3 bytes and receives 3 bytes after that. From my understanding it is the first one, am I right?
Adafruit's library for the MCP3008 has your answer. Check out the read_adc() function:
def read_adc(self, adc_number):
"""Read the current value of the specified ADC channel (0-7). The values
can range from 0 to 1023 (10-bits).
"""
assert 0 <= adc_number <= 7, 'ADC number must be a value of 0-7!'
# Build a single channel read command.
# For example channel zero = 0b11000000
command = 0b11 << 6 # Start bit, single channel read
command |= (adc_number & 0x07) << 3 # Channel number (in 3 bits)
# Note the bottom 3 bits of command are 0, this is to account for the
# extra clock to do the conversion, and the low null bit returned at
# the start of the response.
resp = self._spi.transfer([command, 0x0, 0x0])
# Parse out the 10 bits of response data and return it.
result = (resp[0] & 0x01) << 9
result |= (resp[1] & 0xFF) << 1
result |= (resp[2] & 0x80) >> 7
return result & 0x3FF
It appears that it sends a three-byte command (where only one byte is non-zero):
resp = self._spi.transfer([command, 0x0, 0x0])
The response is three bytes which contains the packed 10-bit ADC value.
resp = self._spi.transfer([command, 0x0, 0x0])
# Parse out the 10 bits of response data and return it.
result = (resp[0] & 0x01) << 9
result |= (resp[1] & 0xFF) << 1
result |= (resp[2] & 0x80) >> 7

Read UART transmision Input buffer in Matlab

I'm trying to make a serial communication between two ESP8266 Wifi chips.
To start, I tried sending a sample data 10 times in a for loop. Here is the code:
Transmiter:
for Packets = 1 : 10
SendData(client,Data(Packets));
end
Receiver:
Packets = 1
while(1)
Data(Packets) = ReceiveData(Server);
Packets = Packets + 1;
if (packets == 10)
break
end
end
it works good. The problem is when I want to send data with some delays, the transmitter should connect to receiver again and the server (receiver) receives some data indicating that connection is made again.
The received Buffer should be:
+IPD,0,1024:ùüþþþýýþþÿÿûûýþýûúþÿúóýÿþþþþþýúøûýþ...
but after reconnecting the received Buffer is:
0,CLOSED %Receiver Prompt, disconnected from Transmiter
0,CONNECT %Receiver Prompt,connected to Transmiter
+IPD,0,1024:ùüþþþýýþþÿÿûûýþýûúþÿúóýÿþþþþþýúøûýþ...
The remaining part of data will be read in next packet and same for next packets.
what should I do to receive just the data?
The send and receive functions:
function ReceivedBuffer = ReceiveData(SerialPort)
ReceivedBuffer = fread(server,1038); %Size data = 1038 Bytes
end
function SendData(SerialPort,Data)
fwrite(SerialPort,Data);
end