09-22-2020 02:59 PM
Hi RavensFan,
I am currently trying to create a VI to read and control a CN616A and I have a few questions about your implementation. Based on my setup and the documentation I found for the device I don't think the ASCII format is being used anymore. I can't seem to wrap my head around how I need to format the request to receive a response that contains the temp data. Attached is the current data sheet that I am working from.
I set my CN616A with the following config:
RS485
Baud: 4800
Parity: Even
Address: 001
I have connected with Omega software and confirmed that with the correct com port selected it can communicate and read from the controller.
09-22-2020 03:25 PM
The new manual you sent shows they have gone from ASCII communication to Modbus.
Search the forums for a lot of communications about ModBUS. LabVIEW has several ModBUS libraries you can use.
Look on JKI VI Package Manager
Or see this link.
The key things you'll need to know:
1. The serial port parameters
2. Slave address of the device
3. Register addresses of the parameters you want to read.
4. Modbus often lists holding registers as starting with a 4. So 40001. But the underlying protocol is zero-based, and that is what the Modbus libraries use. So if you want to read parameter 40022, drop the 4, subtract 1. Then you'll do a Modbus Read at address 21.
09-23-2020 11:40 AM
Thanks RavensFan!
That helped and was able to get me down the road a bit.
I have a few other questions. Searching the forums I was able to find the type cast that takes the register word and converts it to a float. I have verified that it works, but I can not seem to find any information explaining what is actually happening there with the type cast.
Additionally, can you point me to or explain what the proper setup to run multiple actions is? (I feel like I want to say event structure, but I know that is an actual structure) For example, when I run this program I want to have a button that switches between having the controller display in F or C.
My overall goal for the program is to run a test stand for product qualification. First part will be calibration. Set 2 zones to separate specific temps and hold while the operator manually switches a sensor between them to calibrate a sensor to react at those temps. Second part will be putting a calibrated sensor in each zone and have the program cycle through set temp ranges and that will validate the sensor's calibration is correct.
09-23-2020 01:49 PM
For typecast.
A single precision floating point is store as 4 bytes.
You can interpret those 4 bytes a number of different ways.
As two U16 values next to each other, As two I16 values next to each other. As a series of 4 characters in a string.
So typecast just takes that piece of memory and interprets it as a different datatype.
As for running multiple actions, it sounds like you want to look at a state machine architecture. I'd say that is a topic for a new message thread.
09-25-2020 10:27 AM
RavensFan,
Thanks for the explanation. When writing to a register what format does the number need to be in? I can see on the Sub Vi that it has the input as a U16, but when I pass a U16 value of 100 and check it I do not see the 100 returned.
Attached is my latest code. I have seen a ton of your post on the forum going over proper coding methods so I cleaned it up, cleared coercion dots, and generally commented for understanding.
When I finish with this I would like to post my code so there is an updated example on the forum for the CN616A using RTU. Do you think I should post it on this thread or make a new one?
09-25-2020 12:16 PM - edited 09-25-2020 12:16 PM
I would post it in this thread.
You have to read the manual to see what the device is expecting in the registers.
I can tell you that what you are doing is wrong. You are reading a single U16 register, but typecasting that to a Single floating point. If the manual says that you are using a pair of registers and that they represent a single, then you need to combine two registers and typecast to a single. That might be an array of U16's, or it might be taking two individual U16's and joining them before typecasting. Either could work but you have to know if the the registers are arranged high word or low word first. (A word is a 16-bit value.)
09-25-2020 02:34 PM
That is a good point. I think one problem I am having is I am not familiar with this type of documentation enough yet to fully know what it is telling me.
I know when I was reading in the Temp that the information is stored across two registers. They are marked as IEEE floating point values in the manual and the actual registers for the zones increment by two. This is confirmed when I read them in and they fill two registers. (Page 34-35)
The profile registers are also marked as IEEE floating values (page 39) so I am guessing they need two values as well. Although when I read the values that are already set only one register actually has a value showing in the array. (see photo of front panel) If I need to write to two registers what would that look like? I see that the Write Multiple Holding Registers wants a 1D array of U16. 0 I am guessing I need to take the value of 100 and typecast it as a U32, then break that into a hi and lo value to pass into the registers? I attached what I think that code might look like, but it is not working.
I agree with your comment, it does look like I am reading the profile register incorrectly. If they are floats I should be reading in two registers. Interestingly, since the second register is showing as empty I am still getting the correct setpoint reading from them.
09-25-2020 02:35 PM
Here is the manual again.
09-25-2020 04:53 PM
Did you try the changes I showed in my previous message?
I will read 6 consecutive registers as 3 single precision floats. The only thing that may be wrong is the endianess of the matched pairs of registers. We can fix that in a different way.
09-25-2020 06:21 PM
I did. That works and shows the same output I was getting before, but I am sure in a better way programmatically. Since the second register is 0 I was lucky and it didn’t matter if I only read in the first register.
I am still having a problem with the write to multiple registers function which is at the end of the code though. I can read the register and see that I have the setpoint to 130, but I can’t write to it to change it 100. That is what the “write to register.png” is above. It looks like my snippet doesn’t show the input lines very well. The top line holds the address that is calculated using combo boxes and is a U32. That address works because it is the same line that is feeding the address input for the read portion of the code. I have a typecast changing the input value, set to “100” into a U32, that flows into a split numbers block (splits it into 2 words) and then they are fed into a build array so I have a 1D array of U16 with 2 elements. I have tried swapping the hi and lo of the split number block to see if they are wrong and it doesn’t work either way.