02-18-2022 04:16 AM
My current project is to communicate with a SIC dot marker. The comms are pretty simple and the marker uses CR & LF as termination characters for its responses to commands.
I send 'RUNcrlf'
It returns 'RUN OKcrlf'
When the marker finishes marking it then also sends EOT and ENQ control characters
There is no termination character following the last transmission so the code hangs until timeout.
I have attached an image of realterm performing the sequence above.
Either I change the termination character to ENQ when I know the marker is running (if its possible) or I go back to using 'bytes at port' to set the byte count. Responses are not always instant from the marker (for example when requested to load a file) so using a very short timeout would probably lead me into trouble somewhere down the line.
If anyone knows how to deal with the EOT and ENQ or what I use to set the termination character I would appreciate it. For now I will use 'bytes at port' to keep the job moving.
Solved! Go to Solution.
02-18-2022 07:43 AM - edited 02-18-2022 07:43 AM
It's always fun to emulate a terminal program. So the flow is send a command with termination chars, get some running messages with termination chars, then it ends with EOT? Sorry, I'm not familiar with this instrument.
02-18-2022 08:57 AM - edited 02-18-2022 09:00 AM
This sounds like the protocol is inconsistent on the device side.
I would suggest splitting up the communication layers with a Producer/Consumer. Have the producer continuously read the raw data from the line into a buffer and use the consumer to sort out the communication protocol. In the consumer you can then check both for crlf and EOT/ENQ and treat them as termination signals and have it emit the complete messages from there.
02-18-2022 09:11 AM
@STTAndy wrote:
Either I change the termination character to ENQ when I know the marker is running (if its possible)
Here are 3 ideas I just came up with (in no particular order):
1. You can change the termination character with a simple VISA Property Node (Message Based Settings->Termination Character). So you send the command, you get the proper response (be sure to throw an error if you don't get the OK message back), set the termination character to ENQ, wait for the response to come in, and then set the termination character back to a Line Feed.
2. You could use the Bytes At Port to just see if data has come in in a loop (check every X ms for up to Y seconds). If you are expecting the EOT and ENQ, then just read 2 bytes where there is anything in the port and verify what you read.
3. In one application, I had to tell my serial terminal to change to "Binary Mode" where it turned off the termination character and then just dumped everything to a file and my main loop (the device was sending me a ton of data on command that I then had to analyze). The main loop could then search for the specific byte combination telling me the data was done and then tell the serial terminal to go back to "ASCII Mode".
I would need to know a lot more about your architecture before I could make and further recommendations. Given the current state of my serial terminal library, I would probably go with changing to "Binary Mode" (would require the least amount of changes to my library). For what I see most people have, I would probably recommend option 2.
02-18-2022 11:04 AM
@STTAndy wrote:
My current project is to communicate with a SIC dot marker. The comms are pretty simple and the marker uses CR & LF as termination characters for its responses to commands.
I send 'RUNcrlf'
It returns 'RUN OKcrlf'
When the marker finishes marking it then also sends EOT and ENQ control characters
There is no termination character following the last transmission so the code hangs until timeout.
I have attached an image of realterm performing the sequence above.
Either I change the termination character to ENQ when I know the marker is running (if its possible) or I go back to using 'bytes at port' to set the byte count. Responses are not always instant from the marker (for example when requested to load a file) so using a very short timeout would probably lead me into trouble somewhere down the line.
If anyone knows how to deal with the EOT and ENQ or what I use to set the termination character I would appreciate it. For now I will use 'bytes at port' to keep the job moving.
Oh, after Googling SIC, reading their web pages and then trying to get their documentation (I hate it when they require an account to download manuals) As an aside, next time add a link to the device pages.
I see what you have to contend with. Essentially, the Run command is followed by a properly terminated response then the SIC just starts marking. EOT ENQ is then sent when operation is complete.
So, you simply need to treat this case like a Wait on OPC! That is your Mark and Wait.vi should Query Run and if Run OK is seen enter a loop to read 1 byte (not bytes at port) with a short timeout ignoring timeout errors until 1 of 3 exit conditions exist; A) Normal: ENQ is seen "marking complete" success! B) some ungodly time elapsed Communications failure! Like some idiot pulled the USB cable or blew a fuse. C) User Aborted: like somebody closed the application (you never let them see the abort button though right?)
02-18-2022 11:42 AM
Like JpB said, you don't actually need Bytes at Port. Just try to do a read of 1 character with a short timeout, then repeatedly poll it. If you call Read, it'll return whenever it gets the termchar OR times out OR fills the buffer, so you can just say Read and let it time out. Say your timeout is 100ms; you can let it try to read 1 character 30 times. If it returns no characters after 30 tries (or 3 seconds), then it's a "real" timeout.
Yes you could do the same with Bytes at Port, but then you just check characters, then if there are some, you still have to call Read. Doesn't save a lot of effort, but it might be a little clearer what the intent behind the code is.
To repeat, VISA Read will NOT return a timeout error if it's set to termchar/1 character and you receive that character. Termchars are not mandatory for reading when the port is set to Termchar mode.
(Also, sorry you're having to deal with a poorly-formatted serial stream. I've been there and it's no fun.)
02-18-2022 12:16 PM - edited 02-18-2022 12:18 PM
@BertMcMahan wrote:
Like JpB said, you don't actually need Bytes at port
(Also, sorry you're having to deal with a poorly-formatted serial stream. I've been there and it's no fun.)
Not really badly formatted. The device marks parts from marking files in on-board memory. So, the delay between Run OK and completion of marking is unknown. Rather than whip itself into a frenzy like a Chatty Cathy the device simply starts marking. Suppose the mark run contains three files to mark... call them, LOGO_SZx, FWID_MajMin, and DATE_Code. Send Run and I'd bet a doughnut the response is
EOT <when the logo is marked> EOT <when the firmware version is marked> and EOT ENQ <when the date code is marked.>
Actually, nicely done by SIC!
[And, it's a "Þ", alt+0222 win and LongPress T Android] My Alias sounds like "Jay Thornby" 😀
02-18-2022 12:58 PM
Ah my apologies JÞB. Didn't know that the Þ symbol was a thing. I thought it was a stylized p that I couldn't type 🙂
Anyway, as someone with lots of time spent with designing various serial protocols, why is it a good thing that they send EOT and ENQ with no termchar? It seems to me that it's always better to terminate all messages with a termchar (like send EOT /r or whatever) but I'm willing to learn 🙂
02-18-2022 02:07 PM - edited 02-18-2022 02:07 PM
@BertMcMahan wrote:
Anyway, as someone with lots of time spent with designing various serial protocols, why is it a good thing that they send EOT and ENQ with no termchar? It seems to me that it's always better to terminate all messages with a termchar (like send EOT /r or whatever) but I'm willing to learn 🙂
Primarily because it is NOT
While (!OPC)
print "/ BS | BS \ BS -- BS "
Like a Chatty Cathy. And since the Operation Duration cannot be calculated the developer on the other end has some feedback about the total progress of each file to mark.
With either a dot head or a laser overmarking would be bad.
Getting away from the normal term char also allows an abort to be issued and acked independently of the mark progress. So, a reasonable solution to this specific application.
02-18-2022 03:00 PM
Ah, no, I agree sending constant "spinning bar" messages to a terminal program would be bad. I simply meant to keep it exactly the same as it is now, but add a termchar after each transmission.
As I understand it, the protocol you mentioned above is:
<Computer sends RUN to printer/marker>
Run OK [termchar]
<Logo gets marked>
Device sends EOT to computer
<Firmware version marked>
EOT
<Date code marked>
EOT
ENQ
Is that right? All I'm saying is it would seem better to me to do:
<Computer sends RUN to printer/marker>
Run OK [termchar]
<Logo gets marked>
Device sends EOT to computer, termchar
<Firmware version marked>
EOT [termchar]
<Date code marked>
EOT [termchar]
ENQ [termchar]
Basically the same as it works now, just send a termchar after each byte- not a termchar after the marking is done. I don't feel like that would slow things down too much, and would still allow for aborts at any time.
(PS: I really appreciate the discussion. My company has to implement custom PC-MCU serial protocols quite frequently, so any non-traditional tips or tricks are extremely relevant to my work :))