LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

LabVIEW Serial NAK Response

Solved!
Go to solution

So I've been working on this for a while.  I am trying to communicate from a cRIO-9057 to an IPC Mini ion pump controller (link to manual here) using RS232.  For the purposes of this thread, I will focus on window 811, which should measure the current in the device.  When I write the message and then try to read, I get the NAK or Negative Acknowledge response. However, I've found through a lot of trial and error, that if I send an intentionally false message, thereby causing a timeout error, when I next send the correct message, it reads out correctly.  I am not sure why I have to send a bad message and then a good one to get it to respond with the desired data.  

 

When I try the pressure measurement (window 812), I can just send the correct message twice.  The first time responds with an NAK and the second with the correct readout.  I thought it was something to do with the buffer, but I've tried flushing and clearing everything to no avail.

 

I'm attaching the working but bad code (Read Current.vi) and the simple code (Simple Read Current.vi) I wished worked.  I know there is a lot of unnecessary baggage in the bad code (hence the name), but I wanted to read out the number of bytes at port to monitor what was going on.  I also had each write function wired up to select function so I could quickly change the codes to be good or bad.  The working commands are the ones in the hex strings.

 

Any insight or help will be greatly appreciated.

Download All
0 Kudos
Message 1 of 25
(743 Views)

Update:  I modified the "simple" code to have two write and reads consecutively (see attached updated vi), but this time they are both "good" messages.  Now the second one works without needing to throw an error first.  Interestingly, the second response starts with the CRC, which as I understand should come at the end of the message.  I suspect this is leftover from the first message, but I am requesting more bytes than are being transmitted so I don't know why that'd be the case.

0 Kudos
Message 2 of 25
(708 Views)
Solution
Accepted by BovineJoni

@BovineJoni wrote:

Update:  I modified the "simple" code to have two write and reads consecutively (see attached updated vi), but this time they are both "good" messages.  Now the second one works without needing to throw an error first.  Interestingly, the second response starts with the CRC, which as I understand should come at the end of the message.  I suspect this is leftover from the first message, but I am requesting more bytes than are being transmitted so I don't know why that'd be the case.


Of course! You set the termination character to 0x03, so the VISA Read will terminate reading on that character. But the protocol appends the two byte CRC after the <ETX> character. Use of the character 0x3 as termination character for this device protocol is correct but you always need to read an additional 2 bytes after your first VISA Read returns to also read the two CRC bytes.

 

Your Read Current.vi uses for the first command binary byte display mode but for the second command selects the normal display mode string.

 

Something like this should handle both reading and writing values to a specific window. Address is only relevant if you use RS-485 instead of RS-232.

IPCMini Read-Write Value.png

Rolf Kalbermatter
My Blog
Message 3 of 25
(674 Views)

Thanks so much for your help!  That makes sense regarding the termination character.  I tried the VI you wrote, while it does read the correct value (which I find a little strange only because I swear I tried VIs to this effect before), it also throws an error upon the first read:

 

Error -1073807339 occurred at VISA Read in IPCMini Read-Write Value.vi

Possible reason(s):

VISA: (Hex 0xBFFF0015) Timeout expired before operation completed.

 

I changed the status of the error by reducing the number of bytes read.  I set the number of bytes to read to 17 (there are 16 transmitted) but now it tells me:

 

Warning 1073676294 occurred at VISA Read in IPCMini Read-Write Value.vi

Possible reason(s):

VISA: (Hex 0x3FFF0006) The number of bytes transferred is equal to the requested input count. More data might be available.

 

Also, because the termination character was never set, the CRC is included in the first read, so the second read is redundant and throws an error. I'm not too sure if the CRC comparison at the end is necessary, so I might just delete that entirely and have the outputs sent to the front panel instead of first checking the CRC.  What are your thoughts?

0 Kudos
Message 4 of 25
(645 Views)

@BovineJoni wrote:

Also, because the termination character was never set, the CRC is included in the first read, so the second read is redundant and throws an error.


That is the first thing to fix.  Make sure the Termination Character is set to 0x3 (STX).

 


@BovineJoni wrote:

I tried the VI you wrote, while it does read the correct value (which I find a little strange only because I swear I tried VIs to this effect before), it also throws an error upon the first read:

 

Error -1073807339 occurred at VISA Read in IPCMini Read-Write Value.vi

Possible reason(s):

VISA: (Hex 0xBFFF0015) Timeout expired before operation completed.


This points to two possible things: You do not have the Termination Character enabled or the device is taking a very long time to respond.  My money is on the former.

 

In summary your initialization should look something like this:


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 5 of 25
(630 Views)

@crossrulz wrote:

@BovineJoni wrote:

Also, because the termination character was never set, the CRC is included in the first read, so the second read is redundant and throws an error.


That is the first thing to fix.  Make sure the Termination Character is set to 0x3 (STX).

 


@BovineJoni wrote:

I tried the VI you wrote, while it does read the correct value (which I find a little strange only because I swear I tried VIs to this effect before), it also throws an error upon the first read:

 

Error -1073807339 occurred at VISA Read in IPCMini Read-Write Value.vi

Possible reason(s):

VISA: (Hex 0xBFFF0015) Timeout expired before operation completed.


This points to two possible things: You do not have the Termination Character enabled or the device is taking a very long time to respond.  My money is on the former.

 

In summary your initialization should look something like this:


Oh wow, this is fun!  Not only does the response have an ETX termination but, it leaves 2 bytes after the ETX. Also, the ETX is part of the CRC!  So, we actually need to:

  • Enable term char (ETX, 0x03) on reads via a property node BUT also set Term Character DISABLED on writes. [Note: You are getting the NACK because you are appending another ETX as a term char after the CRC on each write so: every other ETX the device sees is preceeded by nothing and that's a NACK!]
  • Write your command as formatted (correctly)
  • Read until term char (VISA Read will throw a warning that the term char was seen and more data may be available.  Ignore that we know a 2byte CRC is hanging out)
  • Append the ETX back into the Read Data
  • Disable term char on reads via property node
  • Read exactly 2 bytes ( to get CRC) (VISA Read will throw a warning that the number of bytes read matched the bytes requested.  you can safely ignore that too! the buffer is empty and no more Data should be available)
  • Compare CRC with Read Data appended with ETX

You gotta love Firmware Engineers, they think of the danmedest ways to do simple serial communications. 

 

<Sea Story>

I once saw a protocol that sent 2 byte data followed by the same bytes inverted followed by a "Checksum" of U16Data XOR U16Inverted Data (NOTE: That Checksum was always 0xFFFF)


"Should be" isn't "Is" -Jay
0 Kudos
Message 6 of 25
(619 Views)

some firmware developers have complicated knots in their brains. Apperently this cannot be repaired.

0 Kudos
Message 7 of 25
(609 Views)

@Martin_Henz wrote:

some firmware developers have complicated knots in their brains. Apperently this cannot be repaired.


Easily fixable by the following method:

  • Remove brain from engineer's cranium 
  • Manipulate excised brain until no knots remain

"Should be" isn't "Is" -Jay
0 Kudos
Message 8 of 25
(607 Views)

@Martin_Henz wrote:

some firmware developers have complicated knots in their brains. Apperently this cannot be repaired.


In my experience, especially with PLC developers, is many engineers make things more complicated in order to justify their ineptitude of providing a solution.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 9 of 25
(597 Views)

As crossrulz already said my example VI assumes that you have properly initialized the session to use a termination character of 0x03.

 

Other than that my routine SHOULD work as intended, be robust and work without any stupid delays to try to synchronize with an external device that you don't have any control of anyways other than what data it returns.

 

Is it a brain damaged protocol? Not really for a binary protocol! It is a bit involved and definitely invented by an embedded firmware programmer, but fairly consistent to handle once you figure out the actual constraints of it. With nowadays ARM and other similar high performance 32-bit embedded CPU, performance is usually not a huge concern anymore, but when using 8-bit micros, you can have some challenges to get a straight forward serial port handler that doesn't completely lock up the rest of your device every time the serial port interrupt occurs.

 

A few rules I handle myself:

- Try to determine the actual end of message character, as in this protocol seen, it may NOT be the last byte in a message but if what follows is constant in size there is not a big problem.

- Use the VISA termination character handling on Reads to deal with this termination character.

- Do NOT use the VISA termination character appending on VISA Writes but instead handle those characters explicitly when generating the message to write.

- Try at all costs to avoid any form of delay or similar function in your communication code. It is in 99.9% of the cases an indication that you have not yet understood the protocol properly.

- Never ever use Bytes at Serial port for anything else than to determine if there is actual data to process. Using the Bytes at Serial Port value to determine how much data to read is in 99.99% of the cases the completely wrong thing to do. And those 0.01% you will never come across!

Rolf Kalbermatter
My Blog
Message 10 of 25
(558 Views)