Response code indication while using Modbus RTU - c#

I am using Modbus RTU protocol to read data. I have Slave Id = 1 and Modbus Address = 40023. I am configuring Start Address = 22. Is it correct with my Modbus Address?
If I am configuring following details:
Slave Id= 1 Baud Rate = 19200 Stop Bits = 2 Data Bits = 8 Parity =
None Start Address = 22
I am reading data with following code
var master = ModbusSerialMaster.CreateRtu(port);
ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, 1); //2 is number of points
With these details I am getting this response in console:
INFO Modbus.IO.ModbusSerialTransport - TX: 1, 3, 2, 0, 0, 184, 68
In above response I only know some of them what they indicate like first digit 1 indicate Slave Id, 3 indicate function Code, 22 indicate Start Address, 2 indicate number of points.
Can anyone please explain me remaining code? What they indicate?
Thanks!

Start address is encoded in two bytes (0, 22). Number of registers is also encoded in two bytes (0, 2). (37, 207) is the CRC, needed in all Modbus RTU frames.

I think your console text is a request package.
Its meaning is in the image below

Related

TcpListener and WebSocket failds: One or more reserved bits are on: reserved1 = 1, reserved2 = 0, reserved3 = 0

Using TcpListener in C# as my server and WebSocket in JavaScript as my client I established a connection and performed an handshake properly, I can receive as much data as I want from my client but I cant seem to send data out, I get the following error on every attempt I make:
One or more reserved bits are on: reserved1 = 1, reserved2 = 0,
reserved3 = 0
Perhaps I need to encode data coming out from my server as part of the WebSocket protocol?
How can one approach this correctly?

Websphere MQ & .NET - WriteString() property makes message too long

So I am trying to send a message to a queue that accepts a string of max 482. The string I am sending it has a length of 452. Here is the block of code where the request queue is accessed:
var openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING;
requestQueue = queueManager.AccessQueue(requestQueueName, openOptions);
var messageObject = new MQMessage();
messageObject.WriteString(message);
openReplyQueue(replyQueueName);
messageObject.ReplyToQueueName = replyQueue.Name;
messageObject.Format = MQC.MQFMT_STRING
messageObject.MessageType = MQC.MQMT_REQUEST;
messageObject.Report = MQC.MQRO_COPY_MSG_ID_TO_CORREL_ID;
messageObject.Expiry = 300;
var pmo = new MQPutMessageOptions();
pmo.Options = MQC.MQPMO_FAIL_IF_QUIESCING;
requestQueue.Put(messageObject, pmo);
The code fails on the last line with the MQException Reason Code 2030. With some console output, I found out that the message length in the MQMessage object is 904, exactly double the length of the string I am trying to send and way longer than the queue's max message length.
How do I keep this buffer from happening and make sure the message length stays at 452?
IBM MQ classes for .NET default to using CCSID 1200 (UTF-16) which is a Double Byte Character Set (DBCS). Because each character is represented as two bytes your 452 character string is represented as 904 bytes.
If the application getting the message from the queue is expecting 452 characters and is using the Get with Convert option, the message will be read correctly by the application. If the reading application is using an ASCII character set then this would be converted and read by the application as 452 bytes. This would also work if the getting application is reading in CCSID 1200 or another DBCS since the application is expecting 452 characters, even in a DBCS it is still getting 452 characters. If this is how your getting application works then one option is to increase the MAXMSGL of the queue to accommodate messages encoded in a DBCS.
Another option is to tell your putting application to put the message in a ASCII character set such as CCSID 437.
To set the CCSID to 437 use the following:
messageObject.CharacterSet = 437;

Windows 10 IOT - RFID RC522 Read UID 7 byte

i'm try to develop Project RFID Reader in windows 10 IOT in c#
i'm use RFID sticker buy from china. refer link below
https://www.aliexpress.com/item-img/10-NFC-13-56-NTAG-213-RFID/32709729334.html
and i'm use example from like below
RFID RC522 Raspberry PI 2 Windows IOT
During test RFID reader. it's work to read UID 4 byte.but i'm try to read 7 byte UID. It 's not working to read.
i'm modify some part of RC522 RFID
internal Uid(byte[] uid)
{
FullUid = uid;
//================ Change to 7 byte ======================
Bcc = uid[7];
Bytes = new byte[7];
System.Array.Copy(FullUid, 0, Bytes, 0, 7);
//Bcc = uid[4];
//Bytes = new byte[4];
//System.Array.Copy(FullUid, 0, Bytes, 0, 4);
foreach (var b in Bytes)
{
if (b != 0x00)
IsValid = true;
}
}
And
public Uid ReadUid()
{
// Run the anti-collision loop on the card
//Transceive(false , PiccCommands.Anticollision_1, PiccCommands.Anticollision_2);
Transceive(false, PiccCommands.Anticollision_1, PiccCommands.Anticollision_2);
// Return tag UID from FIFO
//return new Uid(ReadFromFifo(5));
return new Uid(ReadFromFifo(8));
}
it's still not reading.
So please advise.
There are RC522-based readers on the market that fail to read some IC cards, especially the ones with 7-byte UID. The problem is in slight differences in their antenna coil and capacitors.
The solution is either
to buy a "good" reader (which is hard to distinguish if you are buying it online)
or
to replace the capacitors C8 to C11 (C8+C9 150pF, C10+C11 33pF).
Here you can find a thorough analysis of the problem and the solution:
https://www.eluke.nl/2018/03/08/fixed-rc522-rfid-reader-not-reading-some-cards-part-1/
If the card is an S50 (aka Mifare 1K Classic) card type ISO14444A, they respond with 2Bytes (Cascade 1), 4Bytes (Cascade2) or 7Bytes (Cascade3) as their UID but you have to 'S'elect the card after starting the COM serial port. If, however you are using a reader that uses either ATR or ATS then you get back a string of hexadecimals that describe the card's characteristics. How do you know the difference - its in the documentation about the reader. Chinese cards typically are difficult to read off the starting block - try initialising a card using NFC on your mobile phone first, or just try reading the card with your phone - use TagWriter available on Google Play. Additionally look up the standards for ISO1444A cards - ISO15693 are similar but not the same. Also look at https://lastminuteengineers.com/how-rfid-works-rc522-arduino-tutorial/

How to fix issue sending text to Arduino over bluetooth serial port from C#

I have an Arduino Uno with a Bluesmirf Silver module connected. My Arduino has a temperature sensor which records the temp regularly. The Arduino listens for any string being sent to it over bluetooth and responds with the latest data.
I have written a C# application to fetch this data but I am seeing some strange behaviour. I am using the following code to connect, send a string and get the returned data.
mPort = new SerialPort(mPortName, 115200, Parity.None, 8, StopBits.One);
mPort.Open();
mPort.Write("download");
Thread.Sleep(1000);
while (mPort.BytesToRead > 0)
{
String data = mPort.ReadExisting();
this.BeginInvoke(new Action<String>(AddMessage), data);
}
The data I get back looks like this:
Line added locally within C# application:
Send: download
Lines added based on data received from Arduino:
Read: d???+?
GotData
------
Total Readings, 1069
Num Readings, 360
Lost Readings, 709
Reading Interval, 240000
------
350,19.34
351,19.34
352,19.34
353,20.31
....
All the text looks fine apart from the string which is being echoed back which I sent to the Arduino. Have I done something wrong with the way I sent the data?
FYI - The datasheet for the bluetooth module is here: http://www.sparkfun.com/datasheets/Wireless/Bluetooth/rn-bluetooth-um.pdf
#Jeff - This is the code which I use on my Arduino to receive data: https://github.com/mchr3k/arduino/blob/master/tempsensor/StringReader.cpp
#Jeff - stringDataLen defines the length and I call the overall function from this file: https://github.com/mchr3k/arduino/blob/master/tempsensor/tempsensor.ino
EDIT: Here is the complete source code
Arduino - https://github.com/mchr3k/arduino/tree/master/tempsensor
C# application - https://github.com/mchr3k/arduino/tree/master/serialdownload
The C# code is definitely getting the flow control wrong for some reason. I have switched to use the following code in C# and this gets a string through without corruption.
private void write(SerialPort mPort, string str)
{
foreach (char c in str)
{
mPort.Write(new char[] {c}, 0, 1);
Thread.Sleep(10);
}
}
An incorrect encoding perhaps?
mPort = new SerialPort(mPortName, 115200, Parity.None, 8, StopBits.One);
mPort.Encoding = System.Text.Encoding.ASCII; // Or System.Text.Encoding.UTF8
mPort.Open();
mPort.Write("download");
Read byte-by-byte and check each byte one by one to debug lower level problems. ReadExisting() converts bytes to a String based on the Encoding property.
My issue was caused by me using the SoftwareSerial class to communicate with my Bluetooth module on pins 2 & 3. I was using a baud rate of 115200 which is claimed to be supported on this page: http://arduino.cc/en/Reference/SoftwareSerial
However, this page ( http://arduino.cc/en/Reference/SoftwareSerialBegin ) states that the maximum baud rate supported is actually 9600. I'm not sure whether this is accurate but reducing my baud rate to 9600 has fixed my issue.
I suggest you to decrease communication speed, because there is no reason to use 115200bps (only if your module demand this speed, then it's ok). Also you are sending string "download" which is not good, rather use markers something like "#D" which internally for your Arduino device means, send data to computer. In this way you are sending only two bytes instead eight, and you will decrease probability of error, and Arduino code will be better.
Now, let's try fix the problem. First try use something like this when you are reading data from Arduino device:
ArayList dataReceaved=new ArrayList():
while(serialPort.BytesToRead>0 && serialPort.IsOpen){
dataReceaved.Add(serialPort.ReadByte());
}
So I suggest you to read byte by byte, in this or similar way. Also you shold be careful if you are sending numbers from Arduino device. If you are, then use something like this:
Serial.print(temperatureValue,BYTE);
With this code you explicitly say that data you are sending is byte long. If this not help, please let me know, so we can try something else.

How to calculate the IP range when the IP address and the netmask is given?

When a IP-Range is written as aaa.bbb.ccc.ddd/netmask (CIDR Notation) I need to calculate the first and the last included ip address in this range with C#.
Example:
Input: 192.168.0.1/25
Result: 192.168.0.1 - 192.168.0.126
my good friend Alessandro have a nice post regarding bit operators in C#, you should read about it so you know what to do.
It's pretty easy. If you break down the IP given to you to binary, the network address is the ip address where all of the host bits (the 0's in the subnet mask) are 0,and the last address, the broadcast address, is where all the host bits are 1.
For example:
ip 192.168.33.72 mask 255.255.255.192
11111111.11111111.11111111.11000000 (subnet mask)
11000000.10101000.00100001.01001000 (ip address)
The bolded parts is the HOST bits (the rest are network bits). If you turn all the host bits to 0 on the IP, you get the first possible IP:
11000000.10101000.00100001.01000000 (192.168.33.64)
If you turn all the host bits to 1's, then you get the last possible IP (aka the broadcast address):
11000000.10101000.00100001.01111111 (192.168.33.127)
So for my example:
the network is "192.168.33.64/26":
Network address: 192.168.33.64
First usable: 192.168.33.65 (you can use the network address, but generally this is considered bad practice)
Last useable: 192.168.33.126
Broadcast address: 192.168.33.127
I'll just post the code:
IPAddress ip = new IPAddress(new byte[] { 192, 168, 0, 1 });
int bits = 25;
uint mask = ~(uint.MaxValue >> bits);
// Convert the IP address to bytes.
byte[] ipBytes = ip.GetAddressBytes();
// BitConverter gives bytes in opposite order to GetAddressBytes().
byte[] maskBytes = BitConverter.GetBytes(mask).Reverse().ToArray();
byte[] startIPBytes = new byte[ipBytes.Length];
byte[] endIPBytes = new byte[ipBytes.Length];
// Calculate the bytes of the start and end IP addresses.
for (int i = 0; i < ipBytes.Length; i++)
{
startIPBytes[i] = (byte)(ipBytes[i] & maskBytes[i]);
endIPBytes[i] = (byte)(ipBytes[i] | ~maskBytes[i]);
}
// Convert the bytes to IP addresses.
IPAddress startIP = new IPAddress(startIPBytes);
IPAddress endIP = new IPAddress(endIPBytes);
Invert mask (XOR with ones), AND it with IP. Add 1. This will be the starting range.
OR IP with mask. This will be the ending range.
I learned this shortcut from working at the network deployment position. It helped me so much, I figured I will share this secret with everyone. So far, I have not able to find an easier way online that I know of.
For example a network 192.115.103.64 /27, what is the range?
just remember that subnet mask is 0, 128, 192, 224, 240, 248, 252, 254, 255
255.255.255.255 11111111.11111111.11111111.11111111 /32
255.255.255.254 11111111.11111111.11111111.11111110 /31
255.255.255.252 11111111.11111111.11111111.11111100 /30
255.255.255.248 11111111.11111111.11111111.11111000 /29
255.255.255.240 11111111.11111111.11111111.11110000 /28
255.255.255.224 11111111.11111111.11111111.11100000 /27
255.255.255.192 11111111.11111111.11111111.11000000 /26
255.255.255.128 11111111.11111111.11111111.10000000 /25
255.255.255.0 11111111.11111111.11111111.00000000 /24
from /27 we know that (11111111.11111111.11111111.11100000). Counting from the left, it is the third number from the last octet, which equal 255.255.255.224 subnet mask. (Don't count 0, 0 is /24) so 128, 192, 224..etc
Here where the math comes in:
use the subnet mask - subnet mask of the previous listed subnet mask
in this case 224-192=32
We know 192.115.103.64 is the network: 64 + 32 = 96 (the next network for /27)
which means we have .0 .32. 64. 96. 128. 160. 192. 224. (Can't use 256 because it is .255)
Here is the range 64 -- 96.
network is 64.
first host is 65.(first network +1)
Last host is 94. (broadcast -1)
broadcast is 95. (last network -1)
I would recommend the use of IPNetwork Library https://github.com/lduchosal/ipnetwork.
As of version 2, it supports IPv4 and IPv6 as well.
IPv4
IPNetwork ipnetwork = IPNetwork.Parse("192.168.0.1/25");
Console.WriteLine("Network : {0}", ipnetwork.Network);
Console.WriteLine("Netmask : {0}", ipnetwork.Netmask);
Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast);
Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable);
Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable);
Console.WriteLine("Usable : {0}", ipnetwork.Usable);
Console.WriteLine("Cidr : {0}", ipnetwork.Cidr);
Output
Network : 192.168.0.0
Netmask : 255.255.255.128
Broadcast : 192.168.0.127
FirstUsable : 192.168.0.1
LastUsable : 192.168.0.126
Usable : 126
Cidr : 25
Have fun !
Input: 192.168.0.1/25
The mask is this part: /25
To find the network address do the following:
Subtract the mask from the ip length (32 - mask) = 32 - 25 = 7 and take those bits from the right
In the given ip address
I.e: 192.168.0.1 in binary is:
11111111 11111111 00000000 00000001
Now, taking 7 bits from right '0'
1111111 11111111 00000000 00000000
Which in decimal is:
192.168.0.0 (this is the network address)
To find first valid/usable ip address add +1 to network address I.e: 192.168.0.1
To find the last/broadcast address the procedure is same as that of finding network address but here you have to make
(32-mask) bits from right to '1'
I.e: 11111111 11111111 00000000 01111111
Which in decimal is 192.168.0.127
To find the last valid/usable ip address subtract 1 from the broadcast address
I.e: 192.168.0.126
You might already know this, but to check that you're getting this stuff right have a look at http://www.subnet-calculator.com/ - you can see there how the bits represent the network and host portions of the address.
I know this is an older question, but I found this nifty library on nuget that seems to do just the trick for me:
http://nuget.org/packages/TakeIo.NetworkAddress/

Categories