read the latest line of a serial port

大憨熊 提交于 2019-12-25 00:51:14

问题


I haven't ever written any code in tcl and pretty novice on serial communication, so sorry in advance if my question doesn't make sense.

I'm trying to solve this problem where I want to listen to a serial port and print the updates line by line in SciLab like a normal serial terminal (e.g. Arduino's serial monitor). The Serial Communication Toolbox for Scilab has a readserial macro (source on GitHub):

function buf=readserial(h,n)
   if ~exists("n","local") then
     N=serialstatus(h); n=N(1)
   end
   TCL_EvalStr("binary scan [read "+h+" "+string(n)+"] cu* ttybuf")
   buf=ascii(evstr(TCL_GetVar("ttybuf")));
endfunction

where the TCL_EvalStr interprets a string in tcl. So my questin is how I can change the line:

binary scan [read "+h+" "+string(n)+"] cu* ttybuf

so it only returns the latest non-empty line on the serial port? I would also appreciate if you could eli5 what this line does?

P.S.1. So far from here I tried:

 TCL_EvalStr("binary scan [lindex [split [read -nonewline "+h+" "+string(n)+"] "\n"] end] cu* ttybuf")

but I get the error message:

Error: syntax error, unexpected string, expecting "," or )

In SciLab.

P.S.2. Defining a new function:

function buf=readlnserial(h)
   TCL_EvalStr("binary scan [lindex [split [read -nonewline "+h+"] \"\n\"] end] cu* ttybuf")
   buf=ascii(evstr(TCL_GetVar("ttybuf")));
endfunction

leads to error message:

Undefined operation for the given operands.

check or define function %c_l_s for overloading.

In SciLab terminal.

P.S.3. Commands:

TCL_EvalStr('[split [read -nonewline '+h+'] "\n"]')

or

TCL_EvalStr("[split [read -nonewline "+h+"] '\n']")

both lead to error:

Error: Heterogeneous string detected, starting with ' and ending with ".

In SciLab.

P.S.4. I think if I use the SciLab command TCL_EvalFile instead of TCL_EvalStr I can solve the issue above. I just need to figure out how to pass h to the tcl script and read back ttybuf.

P.S.5. I was able to solve the crazy conflict between SciLab string and "\n" by using curly brackets instead of double quotation:

 TCL_EvalStr("binary scan [lindex [split [read -nonewline "+h+"] {\n}] end] cu* ttybuf")

however it is still not giving what I'm lookking for.

P.S.6. For those who end up here due to the heterogeneous strings with quotation or double quotation, the correct syntax is 'this '"string'" is inside quotation'. Basically single quotation before other single quotation or double quotations turn them into literal characters.


回答1:


First, let's finish taking apart the line:

binary scan [read "+h+" "+string(n)+"] cu* ttybuf

That's really this:

binary scan [read CHANNEL NUM_BYTES] cu* ttybuf

where CHANNEL is really the name of the Tcl channel that you're reading from (which probably ought to be in binary mode but that's out of scope of the code you're showing), and NUM_BYTES is the number of bytes to be read. This is then processed to a list of numbers (written to the Tcl variable ttybuf) which are the unsigned bytes that were read.


Now, you're wanting to use line-oriented reading. Well, Tcl's read command doesn't do that (that's either fixed-buffer or whole-file oriented); you need gets for line-oriented reading. (You never want whole-file oriented processing when reading from a serial line; it never reaches EOF. You can do trickery with non-blocking reads… but that's quite complex.)

The gets command will return the next line read from a channel, with end-of-line marker removed. We can still use it with binary channels (it's a little weird, but not impossible) so that means we can then do:

binary scan [gets CHANNEL] cu* ttybuf

Converting that back through all that wrapper you've got:

function buf=readserialline(h)
   TCL_EvalStr("binary scan [gets "+h+"] cu* ttybuf")
   buf=ascii(evstr(TCL_GetVar("ttybuf")));
endfunction

I renamed it, and I removed all the manipulation of n; lines are lines, and are not of fixed length. (I wonder whether we can retrieve the string directly without converting through a list of bytes; that would be quite a bit more efficient. But that's secondary to getting this working at all.)



来源:https://stackoverflow.com/questions/54935990/read-the-latest-line-of-a-serial-port

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!