I'm trying to read some raw telemetry data via serial. Each message terminates with \r\n and there are 4 kinds of messages.
I setup the port like this:
if exist('s')
fclose(s);
delete(s);
clear s;
end
s = serial('/dev/ttyS99');
s.BaudRate = 57600;
s.BytesAvailableFcnMode = 'terminator';
s.Terminator = 'CR/LF';
s.DataBits = 8;
s.Parity = 'none';
s.StopBits = 1;
s.BytesAvailableFcn = #serial_callback;
s.OutputEmptyFcn = #serial_callback;
fopen(s);
For the calback, i wrote a simple function
function serial_callback(obj, event)
if (obj.BytesAvailable > 0)
[serial_out, count] = fscanf(obj);
disp(count)
end
end
end
Using fscanf, I get random message lengths. For instance, I am searching for a message with length 42, and it only retrieves messages with length near that value (40, 43, 46...).
I i use fread with unspecified size, I allways get a full 512 bytes buffer. If I specify the size in fread with get(obj, 'BytesAvailable), it degenerates in the sizes of fscanf, i.e., totally random.
So, am I doing something wrong, is matlab bad for parsing serial data...?
P.S. I am getting something like 40 messages of 20~40 bytes per second.
Call the callback function everytime a \r\n has been received, using BytesAvailableFcnMode to configure. fscanf should only be called when a line is completely received by the buffer.
Use fgets or fgetl to read one line from file. This will keep all things after the first \r\n in the buffer. I don't have a serial port nor a Tek so I can't verify this to be working for serial ports.
Probably you need a while loop to read all lines in the buffer. Again I'm not sure how serial does callback but it's unlikely to continuously triggering callback function when there's nothing newly arrived after callback has been called.
Related
My issue involves using the RS-232 Simulink RT blocks.
A model is uploaded to the target PC (xPC) and it transmits and receives data from a variable frequency drive (VFD) that controls a motor. The issue arises on the receiving end when I take data and try to send that data to a display block in my model as a string. Code would be helpful here:
disp = uint8(zeros(1,24));
display = uint8(zeros(1,length(disp)));
cmd = 0;
status = stat_lb;
%% Start-Up
% Initialization Period
if (status == 0 || status == 1)
cmd = 0;
msg = uint8('Start up');
display = [msg uint8(zeros( 1, length(disp)- length(msg) ))];
end
...
%Multiple status cases with unique displays.
...
disp = display
So, here the cmd portion functions as expected. As noted above, I want to display the display string on a display block in my Simulink model. As you can see, though, it is of type uint8, so I need to convert it to type string; however, when I pass it through either the ascii2str Simulink block or just place it in the function call (e.g. display = ascii2str(display)) I get the following error message:
Executing the 'CheckData' command produced the following error: Invalid parameter/value pair arguments
My thought is that this has something to do with the fact that I am using MEX and this function (ascii2str) is not supported. Anyways, I am wondering if anyone knows why I receive this error and if there is anything I can do to resolve it.
Oh, and one last thing: I can get the display to work if I just remove the ascii2str; however, the only problem with this is that the display is in uint8 form and not really helpful. So, if there is any other way that I can decode the uint8 to a string I am all ears.
Thanks!
I have found that there is no support for this feature in Simulink RT. One option is to use external functions, but I found it better for my application to simply output a number and have a table in the simulation that explained what each number meant.
I still have problems with Octave. I need to receive large (>10M) images via a web socket connection, process the data and send it back. I work with Octave 4.2.1 in Windows 7, the sockets package is version 1.2.0 and can be found here: https://octave.sourceforge.io/sockets/
Here is the minimal code example:
pkg load sockets;
rcv_sck=socket(AF_INET, SOCK_STREAM, 0);
bind(rcv_sck,12345);
a=listen(rcv_sck,0);
b=accept(rcv_sck);
data = [];
bufflen = 4600;
total = 0;
count = 0;
while (total < 10000)
[buff,count]=recv(b, bufflen);
data = horzcat(data, buff);
total += count;
endwhile
disconnect (b);
disconnect (rcv_sck);
fileID = fopen('data.jpg','w');
fwrite('data.jpg', data);
fclose(fileID);
imshow ('data.jpg')
it can be tested with netcat
ncat.exe 127.0.0.1 12345 < test.jpg
My problem is, that I am not able to receive data bigger than 4608 bytes. If I send more data, the receive array is cut to this size. This is why i choose 4600 bytes as a buffer length. Now I try to put the chunks of small data blocks together to get the correct data.
But this has two serious issues:
1) I have to know the size of the data I am sending, a problem which can be solved by sending the size first as a parameter. In my example i have set the size to 10000 bytes.
2) More important: it is terribly slow. For a jpeg of 170kB it takes 7 seconds to send the data.
Any hints or tipps are greatly appreciated, thank you.
jan
If you want to read data until disconnect I would suggest
data = recv (b, Inf, MSG_WAITALL);
without any loop or horcat. And on your client side (netcat) use -q0:
netcat.exe -q0 localhost 12345 < test.jpg
Btw, if you want to store it on the server side, why don't you use
system ("netcat -l -p 12345 > data.jpg");
in the first place?
I am using asynchronous serial write operation to send data. Using fwrite() I cannot send data if a write operation is already in progress. It returns an error:
Unsuccessful write: An asynchronous write is already in progress.
How can I simply add the extra data I need to write to the existing output buffer, instead of having to wait for it to finish?
Also, I tried to see the number of bytes left to output, but it would either show the full number (511, default size) or zero. So I increased the size of the output buffer to 100,000 sent that many items and plotted the BytesToOutput, this is what I got:
It drops from ~25,000 directly to 0!? Can anyone explain this please?
Here is my code:
instrreset; %closes, deletes and clears all available serial objects
s=serial('/dev/ttyACM0');
s.BaudRate= 1000000;
s.Timeout= 0.1;
s.OutputBufferSize= 100000;
fopen(s);
data=[1:99999];
bytesLeft=zeros(1,100000);
disp('sending data now... wait for it to complete')
tic()
fwrite(s, data, 'uint8', 'async');
f=1;
while ( strcmp(s.TransferStatus, 'write') )
bytesLeft(f)=s.BytesToOutput;
f=f+1;
%disp(s.BytesToOutput)
end
toc()
plot(bytesLeft);
fclose(s);
delete(s);
clear s;
I'm doing a code that will transfer files between two computers. I'm using tcp socket for the connection. The thing is I need to attach sort of headers to the file bytes that I'm sending so the receiveer know that what I'm sending is part of a file. Let's say my header is data. The string I'll send will be: data <file bytes>.
I'm able to send them and the receiver is able to receive them but the file seems corrupted. Though for unformatted text files it works well but for other files it doesn't seem to parse the file efficiently.
while(1){
fp = (char*) malloc (56);
rc = recv(connfd,fp,55,0);
if(strcmp(fp,"stop") == 0){
break;
}
fp = fp + 5; //I do this to skip the 'data<space>" header
wr = write(fd,pf2,rc-5);
tot = tot + wr;
printf("Received a total of %d bytes rc = %d \n",tot, rc);
}
But I've tried sending the file without the header and I get the file uncorrupted but I need to use those 'data' headers for this particular code. What am I doing wrong?
fp = fp + 5; //I do this to skip the 'data<space>" header
But you don't receive the data<space> header in every receive() call. You have to keep a buffer to which you add all data you receive, until you encounter another "data<space>".
Please note though that separators are generally a bad idea. What if you send a file that has the string "data<space>" in it? Your client will assume that after that, a new file will be sent, while in fact you're still receiving the original file.
Try to send some kind of message-length-header, for example an uint32, which occupies four bytes before each file you send. You can then read the first four bytes and then you know how many more bytes you can expect for that file.
I have a loop that reads from a socket in Lua:
socket = nmap.new_socket()
socket:connect(host, port)
socket:set_timeout(15000)
socket:send(command)
repeat
response,data = socket:receive_buf("\n", true)
output = output..data
until data == nil
Basically, the last line of the data does not contain a "\n" character, so is never read from the socket. But this loop just hangs and never completes. I basically need it to return whenever the "\n" delimeter is not recognised. Does anyone know a way to do this?
Cheers
Updated
to include socket code
Update2
OK I have got around the initial problem of waiting for a "\n" character by using the "receive_bytes" method.
New code:
--socket set as above
repeat
data = nil
response,data = socket:receive_bytes(5000)
output = output..data
until data == nil
return output
This works and I get the large complete block of data back. But I need to reduce the buffer size from 5000 bytes, as this is used in a recursive function and memory usage could get very high. I'm still having problems with my "until" condition however, and if I reduce the buffer size to a size that will require the method to loop, it just hangs after one iteration.
Update3
I have gotten around this problem using string.match and receive_bytes. I take in at least 80 bytes at a time. Then string.match checks to see if the data variable conatins a certain pattern. If so it exits. Its not the cleanest solution, but it works for what I need it to do. Here is the code:
repeat
response,data = socket:receive_bytes(80)
output = output..data
until string.match(data, "pattern")
return output
I believe the only way to deal with this situation in a socket is to set a timeout.
The following link has a little bit of info, but it's on http socket: lua http socket timeout
There is also this one (9.4 - Non-Preemptive Multithreading): http://www.lua.org/pil/9.4.html
And this question: http://lua-list.2524044.n2.nabble.com/luasocket-howto-read-write-Non-blocking-TPC-socket-td5792021.html
A good discussion on Socket can be found on this link:
http://nitoprograms.blogspot.com/2009/04/tcpip-net-sockets-faq.html
It's .NET but the concepts are general.
See update 3. Because the last part of the data is always the same pattern, I can read in a block of bytes and each time check if that block has the pattern. If it has the pattern it will mean that it is the end of the data, append to the output variable and exit.