Issue sending/receiving data over serial connection using MATLAB - matlab

I recently connected a reactor control tower through a serial 'COMMS' port to my computer (serial to USB). It seems to create a connection on the COM4 port (as indicated on the control panel 'devices and printers' section). However, it always gives me the following message when i try to 'fwrite(s)' or 'fscanf(s)'.
Warning: Unsuccessful read: The specified amount of data was not returned within the Timeout period..
%My COM4
s = serial('COM4');
s.BaudRate = 9600;
s.DataBits = 8;
s.Parity ='none';
s.StopBits = 1;
s.FlowControl='none';
s.Terminator = ';';
s.ByteOrder = 'LittleEndian';
s.ReadAsyncMode = 'manual';
% Building write message.
devID = '02'; % device ID
cmd = 'S'; % command read or write; S for write
readM = cell(961,3);% Read at most 961-by-3 values filling a 961–by–3 matrix in column order
strF = num2str(i);
strF = '11'; %pH parameter
strP = '15'; %pH set point
val = '006.8'; %pH set value
msg_ = strcat('!', devID, cmd, strF, strP, val);%output the string
chksum = dec2hex(mod(sum(msg_),256)); %conversion to hexdec
msg = strcat(msg_,':', char(chksum), ';');
fopen(s); %connects s to the device using fopen , writes and reads text data
fwrite(s, uint8(msg)); %writes the binary data/ Convert to 8-bit unsigned integer (unit8) to the instrument connected to s.
reply=fscanf(s); %reads ASCII data from the device connected to the serial port object and returns it to reply, for binary data use fread
fclose(s); %Disconnect s from the scope, and remove s from memory and the workspace.
This leads me to believe that the device is connected but is not sending or receiving information and I am unsure as to how I can configure this or even really check if there is communication occurring between the tower and my computer.

Related

Most simple network protocol for a remote function call?

I am looking for the most simple protocol to program a remote function call, e.g. from Matlab to Julia.
[out1, out2, ...] = jlcall(socket, fname, arg1, arg2, ...);
fname is a string, all other input and output variables are numerical arrays (or other structures known to both sides) on Linux, Windows as option.
Client: open connection, block, pack and transmit
Server: receive, unpack, process, pack and transmit back
Client: receive, unpack, close connection and continue
The solutions I've seen (tcp, zmq) were built with old versions and do no longer work.
Protocol could (should?) be limited to do the pack/transmit - receive/unpack work.
UPDATE
Here is what I have come up with using pipes:
function result = jlcall(varargin)
% result = jlcall('fname', arg1, arg2, ...)
% call a Julia function with arguments from Matlab
if nargin == 0 % demo
task = {'foo', 2, 3}; % demo fun, defined in jsoncall.jl
else
task = varargin;
end
% create pipe and write function and parameter(s) to pipe
pipename = tempname;
pipe = java.io.FileOutputStream(pipename);
pipe.write(uint8(jsonencode(task)));
pipe.close;
% run Julia and read result back
system(sprintf('julia jsoncall.jl %s', unixpath(pipename)))
fid = fopen(pipename, 'r');
c = fread(fid);
result = jsondecode(char(c'));
fclose(fid);
function path_unix = unixpath(path_pc)
%convert path to unix version
path_unix = path_pc;
path_unix(strfind(path_unix,'\'))='/';
# jsoncall.jl
using JSON3 # get JSON3.jl from repository first
function foo(a,b) # demo function
a+b, a*b
end
jsonfile = ARGS[1] # called as > julia jsoncall.jl <json_cmdfile>
io = open(jsonfile, "r") # open IOStream for read
data = read(io) # read UTF8 data from stream
close(io) # close stream
cmd = JSON3.read(String(data)) # unpack stream into [fun, farg] array
fun = Symbol(cmd[1]) # first element is Julia function name,
result = #eval $fun(cmd[2:end]...) # others are function arguments
io = open(jsonfile, "w") # open IOStream for write
write(io, JSON3.write(result)) # (over-)write result back to stream
close(io) # close stream
Open points:
my first use of pipes/streams
output formatting: where Julia outputs a tuple of two, Matlab creates an an nx2 array.
replace json by msgpack for performance, might help with type formatting as well.
Your comments are welcome!
Here is a stripped down way of doing it. If you are going to vary your functions and arguments, a REST as in the comments server is going to be more flexible and less likely to pose a security risk (as you are eval()ing arbitrary code in some cases).
#server code
using Sockets
const port = 6001
const addr = ip"127.0.0.1"
const server = listen(addr, port)
while true
try
#info "Server on $port awaiting request..."
sock = accept(server)
#info "Server connected."
msg = strip(readline(sock))
#info "got message $msg"
fstr, argstr = split(msg, limit=2)
x = parse(Float64, argstr) # or other taint checks here...
ans = eval(Meta.parse(fstr * "($x)"))
#info "server answer: $ans"
write(sock, "$ans\n")
catch y
#info "exiting on condition: $y"
end
end
# client code
using Sockets
port = 6001
server = ip"127.0.0.1"
sock = connect(server, port)
#info "Client connected to $server"
func = "sinpi"
x = 0.5
#info "starting send"
write(sock, "$func $x\n")
flush(sock)
#info "flushed send"
msg = strip(readline(sock)) # read one line of input and \n, remove \n
ans = parse(Float64, msg)
println("answer is $ans")
close(sock)

Read UART transmision Input buffer in Matlab

I'm trying to make a serial communication between two ESP8266 Wifi chips.
To start, I tried sending a sample data 10 times in a for loop. Here is the code:
Transmiter:
for Packets = 1 : 10
SendData(client,Data(Packets));
end
Receiver:
Packets = 1
while(1)
Data(Packets) = ReceiveData(Server);
Packets = Packets + 1;
if (packets == 10)
break
end
end
it works good. The problem is when I want to send data with some delays, the transmitter should connect to receiver again and the server (receiver) receives some data indicating that connection is made again.
The received Buffer should be:
+IPD,0,1024:ùüþþþýýþþÿÿûûýþýûúþÿúóýÿþþþþþýúøûýþ...
but after reconnecting the received Buffer is:
0,CLOSED %Receiver Prompt, disconnected from Transmiter
0,CONNECT %Receiver Prompt,connected to Transmiter
+IPD,0,1024:ùüþþþýýþþÿÿûûýþýûúþÿúóýÿþþþþþýúøûýþ...
The remaining part of data will be read in next packet and same for next packets.
what should I do to receive just the data?
The send and receive functions:
function ReceivedBuffer = ReceiveData(SerialPort)
ReceivedBuffer = fread(server,1038); %Size data = 1038 Bytes
end
function SendData(SerialPort,Data)
fwrite(SerialPort,Data);
end

Uploading sketch in Arduino

I am working on making an interface between MATLAB and Arduino. In other words, I want to send some data from MATLAB to Arduino. I have written programs both in MATLAB and the Arduino IDE.
MATLAB program:
c = 1;
if (c ~= 0 )
f = 1;
else
disp('vhxhjf');
end
disp(f)
arduino=serial('COM5','BaudRate',9600); % create serial communication object on port COM4
fopen(arduino); % initiate arduino communication
while f
fprintf(arduino,'%s',char(f)); % send answer variable content to arduino
end
fclose(arduino); % end communication with arduino
Code for Arduino:
int ledPin = 13;
int matlabData ;
void setup() {
pinMode(13,OUTPUT);
Serial.begin(9600);
// turn the LED on when we're done
// digitalWrite(13, HIGH);
}
void loop() {
if(Serial.available() > 0 ) {
matlabData = Serial.read();
if ( matlabData != 0) {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13,LOW);
delay(1000);
}
else
digitalWrite(13,LOW);
}
}
The problem is whenever I am uploading the sketch , this error is being thrown regularly in arduino ide:
avrdude: ser_open(): can't open device "\\.\COM5": The system cannot find the file specified
It was works on the first try, but after that the above error is thrown continuosly .
Also in matlab, after the first try , the following error is thrown:
enter code here
Error using serial/fopen (line 72)
Open failed: Port: COM5 is not available. No ports are available.
Use INSTRFIND to determine if other instrument objects are connected to requested device.
Error in SP (line 65)
fopen(arduino); % initiate arduino communication
>> instrfind
Instrument Object Array
Index: Type: Status: Name:
1 serial open Serial-COM5
2 serial closed Serial-COM5
and also the command instrfind is showing that the com5 port is closed after the first try.
I have tried the solution given in this link but it is didn't work:
http://forum.arduino.cc/index.php?topic=48421.0
This usually happens when you don't close the port.
In your code, when do you close it? When is f changed so the loop exits?
According to these people, you can try to do
delete(instrfindall)
before trying to open the port or
fopen(arduino);
closeFID = onCleanup(#() fclose(arduino));
...
IMHO the second solution looks better (less destructive)
BTW: put a delay or a sleep (I don't know how this is done in ML) in the fprintf loop, otherwise you will send too many data to the poor Arduino...

Reading data only when present

I'm trying to read the data from the COM3 port.
I'm using this code:
in = fscanf(s);
if(in == 'A')
fclose(s);
break;
end
The problem is that when no data is sent to the com3 port, the fscanf() will wait for a certain time interval and then give a timeout.
Is there a way to read data only when it is present?
Read only when data present
You can read out the BytesAvailable-property of the serial object s to know how many bytes are in the buffer ready to be read:
bytes = get(s,'BytesAvailable'); % using getter-function
bytes = s.BytesAvailable; % using object-oriented-addressing
Then you can check the value of bytes to match your criteria. Assuming a char is 1 byte, then you can check for this easily before reading the buffer.
if (bytes >= 1)
in = fscanf(s);
% do the handling of 'in' here
end
Minimize the time to wait
You can manually set the Timeout-property of the serial object s to a lower value to continue execution earlier as the default timeout.
set(s,'Timeout',1); % sets timeout to 1 second (default is 10 seconds)
Most likely you will get the following warning:
Unsuccessful read: A timeout occurred before the Terminator was
reached..
It can be suppressed by executing the following command before fscanf.
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
Here is an example:
s = serial('COM3');
set(s,'Timeout',1); % sets timeout to 1 second (default is 10 seconds)
fopen(s);
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
in = fscanf(s);
warning('on','MATLAB:serial:fscanf:unsuccessfulRead');
if(in == 'A')
fclose(s);
break;
end

VB6 RS232 not receiving full data from device using MSCOMM Controll

I have a clinical device that sends data on com port, I want to receive data from device
it also received First Frame (254) character after send ACK on ENQ
it receive [ETB] [CR][LF] characters
then I again send ACK for next frame, but not receive data
only receiving EOT char
Device Communication as per device is:
<-[ENQ]
->[ACK]
<-[STX]1H|**********************-[ETB]21[CR][LF]
->[ACK]
<-[STX]1H|**********************-[ETX]8E[CR][LF]
->[ACK]
<-[EOT]
my code is:
'MSComm1.Settings = "9600,n,8,1"
'MSComm1.InputLen = 1
Private Sub MSComm1_OnComm()
Dim InBuff As String
InBuff = MSComm1.Input
if Chr$(5)=InBuff then 'ENQ received
MSComm1.Output=Chr$(6) & VbCr
elseif Chr$(10)=InBuff then 'LF received
MSComm1.Output=Chr$(6) & VbCr
else
text1.text=text1.text & InBuff
end if
End Sub
Device sending full data because 1 software comes with device which receive full data as
but I didn't receive next frame after send ACK again,
if any one have idea what output have to send FOR next ACK, please advice me
thanks in advance
Do something like this...
MSComm1.InputLen = 1 ' for sending single character from device
MSComm1.RThreshold = 1 ' for firing events on receiving a single character
Dim InBuff As String
if MSComm1.CommEvent = comEvReceive then
do
InBuff = MSComm1.Input
Loop Until MSComm1.InBufferCount < 1
Firstly receive all the data and after that use that in your own way.