Details
Bug#: 3829
: Scilab software
: Strings
Status: RESOLVED
Resolution: WONTFIX
Opened: 2008-12-06 23:16
: PC
: All OS
: 5.0.2 final version
: P5
: Minor
Last modified: 2010-04-29 13:53:56

:
Reproductibility: Every Times
:
:
  Show dependency tree - Show dependency graph
People
Reporter: Artur
Assigned To: Enrico SEGRE
Detailed description of the problem
Hello,

I try to use the Serialtoolbox of Enrico Segre 
(http://www.weizmann.ac.il/home/fesegre/scistuff/Serial.tgz)
it's the only toolbox that run under SciLab 5.x.This toolbox is written in TCL. I can send some data via RS232
to a nother PC, but the second PC receive some different data and I can not send and receive a ascii(0)!(ascii(0) could
be a problem of the toolbox)

I think it's a problem of TCL "fconfigure -translation binary".
So the translation works false. 
Look at example. I hope that is the right site to post that problem and hope you can help me to avoid that 'bug', if
not please send me a link to a right forum or TCL bug tracking site.
                    
Text of the scilab error message
just for sending ascii(0)

st=writeserial(h,ascii(0));
!--error 999 
TCL_EvalStr,  at line 1
        missing close-brace
    while executing
"set writeresult [catch {puts -nonewline file9d11ac8 {"
at line      11 of function writeserial called by :  
writeserial(h,ascii(0))
                    
Steps to reproduce the bug
(you need the serialtoolbox to reproduce the "bug")
for example:

kmd=[109 112 102 205 204 140 63 205 204 140 63 205 204 140 63 205 204 140 63...
205 204 140 63 205 204 140 63 16 3];

hnd=openserial(5,"19200,n,8,1","binary");

k = ascii(kmd)

k = mpfÍÌŒ?ÍÌŒ?ÍÌŒ?ÍÌŒ?ÍÌŒ?ÍÌŒ?

st=writeserial(hnd,k)

read data on second PC:

r=readserial(hnd2)

r=mpfÍ??Í??Í??Í??Í??Í??

r=ascii(r)
r=109 112 102 205 12 --- 63 205 12 --- 63 205 12 --- 63 205 12 --- 63 205 12 
--- 63 205 12 --- 63 16 3
(--- are bissing bytes and 12 is false too)

I can not use that received data, cause it's faulty.
                    
------- Comment #1 From Enrico SEGRE 2008-12-07 10:47:01 -------
The first thing which occurs to me is that this might be another manifestation of bug 2520 (after all, not a bug, but
logical tcl behavior). readserial() just uses TCL_GetVar.

As for \0's, a side effect of C \null string termination either in tcl or in the scilab glue: 

-->TCL_SetVar("a",ascii([1 0 2 3]))
 ans  =

  T  

-->ascii(TCL_GetVar("a"))                
 ans  =

    1.  


However there should be workarounds, otherwise the serial toolbox is simply not fit, no excuses. I'd have a look under
the tcl command "binary", and would perhaps resort in the serial toolbox to pass the data as numeric array (inefficient
but failsafe). As already written privately to the OS, I just need some time ahead for it, I'll be travelling next
week.

Enrico
      
------- Comment #2 From Artur 2008-12-07 20:36:05 -------
I have opened a com port with 'mopen' and send the same kmd with the 'mfprintf'

fd=mopen('COM5','r+');
(i wondert that mopen opend a comport with this handle(19200,0,8,1))

mfprintf(fd,'%s',ascii(kmd)) (kmd look at Steps to reproduce the bug)

I get the same kmd-vector on my second PC, but the ascii(0) problem still there.

mfprintf sends nothing after ascii(0)

like:

kmd=[109 112 102 205 204 140 63 205 204 140 63 205 204 140 0 0 63...
205 204 140 63 205 204 140 63 16 3];

after: mfprintf(fd,'%s',ascii(kmd))

i get just [109 112 102 205 204 140 63 205 204 140 63 205 204 140]
      
------- Comment #3 From Enrico SEGRE 2008-12-07 21:47:30 -------
(In reply to comment #2)
> I have opened a com port with 'mopen' and send the same kmd with the 'mfprintf'
> 
> fd=mopen('COM5','r+');

that might be a windows only contraption , i.e. not a solution, if it ever seems to work.

> mfprintf(fd,'%s',ascii(kmd)) (kmd look at Steps to reproduce the bug)
> 
> I get the same kmd-vector on my second PC, but the ascii(0) problem still
> there.

most likely also \0 terminated C-like strings here too. Anyway, that is another route.

As for the TCL way, I'm thinking at a workaround like this (to be tested yet)

function result=writeserial(h,buf)
   if ~exists("buf","local") then 
      TCL_EvalStr("set writeresult [catch {flush "+h+"}]")
   else
      TCL_EvalStr("set writeresult [catch {puts -nonewline "+h+..
                  " [binary format c* {"+mprintf(ascii(buf),%d)+..
                  "}]; flush "+h+"}]")
   end
   result=-eval(TCL_GetVar("writeresult"));
endfunction

TODO is to test it, to figure out the solution for setserial (with binary scan, perhaps), to repackage the toolbox...
      
------- Comment #4 From Enrico SEGRE 2008-12-07 22:10:33 -------
Correction:

function result=writeserial(h,buf)
   if ~exists("buf","local") then 
      TCL_EvalStr("set writeresult [catch {flush "+h+"}]")
   else
      TCL_EvalStr("set writeresult [catch {puts -nonewline "+h+..
                  " [binary format c* {"+msprintf(" %d",ascii(buf(:))')+..
                  "}]; flush "+h+"}]")
   end
   result=-eval(TCL_GetVar("writeresult"));
endfunction


And for readserial something along the lines of:

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)+"] c* ttybuf")
   buf=ascii(TCL_GetVar("ttybuf"));
// convert signed to unsigned chars here??
endfunction


But I have nothing to test it on at the moment.
Btw, I have assumed format c*, since I'm not awae of serial formats wider than 8bits.

Enrico
      
------- Comment #5 From Artur 2008-12-08 00:08:11 -------
(In reply to comment #4)
Hmm... think I have to describe my kmd-vector.
It consists of a string convert to ascii. ( the first three numbers and the rest are axis positions).

For example: 

kmd=[uint8(ascii('mpf')) uint8([205 204 140 63 205 204 140 63 205 204 140 ...  0 0 63 205 204 140 63 205 204 140 63 16
3])];
// the axis position is a ieee754 format 
//A=ftoieee754(1.1) <---- ftoieee754 is a handcoded function
//A= 205 204 140 63
Now I have to send the kmd to my real-time-OS. If the rtos read the kmd-vector it must the same as I send it.


>       TCL_EvalStr("set writeresult [catch {puts -nonewline "+h+..
>                   " [binary format c* {"+msprintf(" %d",ascii(buf(:))')+..
>                   "}]; flush "+h+"}]")

in the kmd-vector are the first three numbers ascii-coded and at this line it will be coded back. Ascii([109 112 102
205 204 140 63]) try to code back to mpf and the axis to ascii(). (type string '%s')
I tried to replace '%d' with '%s' but i get a result = -1


> And for readserial something along the lines of:

>    buf=ascii(TCL_GetVar("ttybuf"));
The rtos send at the end 'Transmission OK'/'Transmission FAULT' in ascii-code (at the beginning mybe sends position
coordinates )
for example:
Transmission OK =>84 114 97 110 115 109 105 115 115 105 111 110 32 79 75

and with 'buf=ascii(TCL_GetVar("ttybuf"));' the numbers will be code to ascii back
for example: the 84 will be code back to [56 52].
At the first version of the readserial function I got the 'Transmission FAULT' sentence not the ascii-code after
reading the port.

I know that is really difficult and I thank you again for the help.
      
------- Comment #6 From Enrico SEGRE 2008-12-08 14:55:29 -------
(In reply to comment #5)
> (In reply to comment #4)
> Hmm... think I have to describe my kmd-vector.

Not really. My goal is to fix the functions so that any string of (8bit) characters is supported, irrespective of the
purpose.

> It consists of a string convert to ascii. ( the first three numbers and the
> rest are axis positions).
> 
> For example: 
> 
> kmd=[uint8(ascii('mpf')) uint8([205 204 140 63 205 204 140 63 205 204 140 ... 
> 0 0 63 205 204 140 63 205 204 140 63 16 3])];

wait - writetoserial expects a string argument. In principle I could make it accepting a numeric array as well, and
silently avoid to recast it to numbers, depending on the type of the argument. However, in the attempted fix (provided
it ever works) I gave above, I assumed that kmd was a string. Remember that ascii(number)=string and
ascii(string)=number.

> and the axis to ascii(). (type string '%s')
> I tried to replace '%d' with '%s' but i get a result = -1

no, %d. I want numbers there. I want that the command passed to TCL_EvalStr
looks like


puts -nonewline file123ab678 [binary format c* {205 204 140 63 205 204 }]

> > And for readserial something along the lines of:
> 
> >    buf=ascii(TCL_GetVar("ttybuf"));
> The rtos send at the end 'Transmission OK'/'Transmission FAULT' in ascii-code
> (at the beginning mybe sends position coordinates )
> for example:
> Transmission OK =>84 114 97 110 115 109 105 115 115 105 111 110 32 79 75
> 
> and with 'buf=ascii(TCL_GetVar("ttybuf"));' the numbers will be code to ascii
> back
> for example: the 84 will be code back to [56 52].

If there are \x00's in this string, TCL_GetVar will see them as end of string. That's the point. If by chance some
sequence of bytes (where typically the first is>128) makes sense as multibyte character in the current encoding,
TCL_GetVar will try to render it as an exotic character, mangling the data. And if it flags a multibyte character, but
does not make sense, TCL_GetVar will replace it wit - - - or ? ? ?, still bad.

That's why readserial should be rewritten, IIUC as above - but I have to test it when I have some time; as above, it
might very well be broken.
      
------- Comment #7 From Artur 2008-12-08 17:31:54 -------
Yes you're right with the writeserial (at Comment #6), I'm sorry . The solution that you written in Comment #4 works
and I can transmit the data without misstakes.

I recognised that the function ascii() and char() have some problems with 0 too.

ascii([84 114 97 0 110 115 109])
ans = Tra

//but the length of ans still 7

k=ascii(ans)
k = 84 114 97 0 110 115 109


The same with the function char():

char([84 114 97 0 110 115 109])
ans = Tra
      
------- Comment #8 From Enrico SEGRE 2008-12-08 18:13:48 -------
(In reply to comment #7)
> Yes you're right with the writeserial (at Comment #6), I'm sorry . The solution
> that you written in Comment #4 works and I can transmit the data without
> misstakes.
> 
> I recognised that the function ascii() and char() have some problems with 0
> too.
> 
> ascii([84 114 97 0 110 115 109])
> ans = Tra
>
> //but the length of ans still 7
> 
> k=ascii(ans)
> k = 84 114 97 0 110 115 109
> 
> 
> The same with the function char():
> 
> char([84 114 97 0 110 115 109])
> ans = Tra

That is a (display?) bug of scilab 5, I guess once more because of the use of C string functions rather than Fortran
for the display. In 4.1.2

 -->ascii([84 114 97 0 110 115 109])
 ans  =

 Transm   

-->ascii(ans)
 ans  =

    84.    114.    97.    0.    110.    115.    109.  

Would you be so kind to open a separate bug for this?
Enrico
      
------- Comment #9 From Enrico SEGRE 2008-12-08 23:03:13 -------
> At the first version of the readserial function I got the 'Transmission FAULT'
> sentence not the ascii-code after reading the port.


Would you try out this one, which has some chance of working?

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)+"] c* ttybuf")
   buf=ascii(evstr(TCL_GetVar("ttybuf")));
endfunction


If it does, when I can I'll post a corrected toolbox. Perhaps with tcl variables in a protected namespace, or some
other improvement.
Enrico
      
------- Comment #10 From Artur 2008-12-10 10:26:43 -------
(In reply to comment #9)


> Would you try out this one, which has some chance of working?
> 
> 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)+"] c* ttybuf")
>    buf=ascii(evstr(TCL_GetVar("ttybuf")));
> endfunction

The readserial works and shows the rigth sentence until a zero. (bug of ascii)
      
------- Comment #11 From Enrico SEGRE 2008-12-18 18:19:53 -------
(In reply to comment #10)

> The readserial works and shows the rigth sentence until a zero. (bug of ascii)

you mean: it retrieves the string including the zeros [please check with ascii(readserial()) ] but the string is not
displayed beyond the zeroes because of the *display* bug, correct?
      
------- Comment #12 From Enrico SEGRE 2008-12-18 18:32:46 -------
(In reply to comment #11)
 but the string is not displayed beyond the zeroes because
> of the *display* bug, correct?

besides, bug 3831 is solved now       
      
------- Comment #13 From Enrico SEGRE 2009-01-12 10:13:36 -------
For the record, I've repackaged the corrections as Serial-0.2 and put it on
http://www.weizmann.ac.il/home/fesegre/scistuff.html. The help files are still in 4.x format, as long as I cant't
figure out how to build help in scilab 5 [nor I'm sure that the process works anymore with 4.1.2]; should I succeed,
someday I might include both help formats in the package, and builder/loader working for both versions.
I don't close the bug yet as I'd like to test the functions once more, which I might do as soon as someone drops on my
table a serial instrument whatsoever.
Enrico
      
------- Comment #14 From Vincent COUVERT 2010-04-29 13:53:56 -------
As this bug refers is not a Scilab bug, I set it to WONTFIX.
      

Attachments


Note

You need to log in before you can comment on or make changes to this bug.

Related actions