Using MATLAB to read out strings from Arduino

조회 수: 32 (최근 30일)
Hieu Philip Hoang
Hieu Philip Hoang 2018년 12월 14일
댓글: Walter Roberson 2018년 12월 18일
Hey guys
I am trying to create a resistance measurer using an Arduino Uno and read out the data with MATLAB. For this, I wrote a programm in MATLAB, which sends a string over serial to the Arduino. For the Arduino I wrote a C-Code, which starts the measurement when the string is received and then computes the resistance (over a voltage divider).
Here are my codes:
MATLAB:
%INITIALIZE THE SERIAL PORT
s = serial('com3');
set(s, 'BaudRate', 9600); % set BaudRate to 9600
set(s, 'Parity', 'none'); % set Parity Bit to None
set(s, 'DataBits', 8); % set DataBits to 8
set(s, 'StopBit', 1); % set StopBit to 1
%OPEN THE SERIAL PORT
fopen(s);
%Send I over serial to arduino
fprintf(s,'%s','I');
%Now the Arduino receives an I, which starts the measurement.
%After measuring the voltage in the voltage divider, the C-Code computes the resistance
%and sends it back over serial as a string
%For example if the measured resistance is 1000, "I1000" will be send back over serial.
%Wait few secs for the Arduino to do things
pause(10);
%receive string from serial
%MATLAB receives the string "I1000"
stringI = fgets(s);
%and creates a new string by extracting the numbers behind I for the resistance
stringI_R2 = extractAfter(stringI,2);
%convert the extracted string "1000" to a number
R2 = str2double(stringI_R2);
%and display it
disp(R2);
fclose(s);
delete(s);
clear s;
ARDUINO:
int analogPin= 0;
int measure;
%input voltage is set to 5 V
int Vin= 5;
float Vout;
%known resistor in voltage divider is set to 100 Ohms
float R1= 100;
float R2;
float x;
void setup()
{
%Start Serial at baudrate 9600
Serial.begin(9600);
%Set Timeout of Serial.read to 3 ms
Serial.setTimeout(3);
}
void loop()
{
%while serial port is availible
while(Serial.available()>0){
%Now, MATLAB sends the String "I" over serial to the Arduino.
%read out the sent string
String rec_string = Serial.readString();
%check if the first sent character is
if (rec_string[0] == 'I'){
%Read out the voltage on Pin 0
raw= analogRead(analogPin);
%compute the resistance out of the measured voltage on pin 0
x= measure * Vin;
Vout= (x)/1024.0;
x= (Vin/Vout) -1;
R2= R1 * x;
%convert the resitance value to a string
String string_R2 = String(R2);
%create new string to send. For example, if
String send_string = "I" + string_R2;
%this string is sent over serial back to MATLAB
Serial.print(send_string);
delay(1000);
}
}
Now, I'm facing the problem, that it does not work. As Error warning inside MATLAB I received the following:
_________________
>Warning: A timeout occurred before the Terminator was reached.
'serial' unable to read any data. For more information on possible reasons, see Serial Read Warnings.
>Error using extractAfter (line 47)
Numeric position exceeds the number of characters in element 1.
>Error in measure_resistance (line 19)
stringI_R2 = extractAfter(stringI,2);
_________________
So thats where I wanted to ask you guys, if anybody see any problem in my code, as I don't really find any. I suggest that there may occur some problems with in sending and receiving the data at the right time, but if anybody has a solution to this, I would be very thankful!
Thanks for reading
Best regards

답변 (1개)

Koundinya
Koundinya 2018년 12월 18일
As the error message suggests, the serial connection is being timed out when reading from serial using fgets. I suspect this is due to the absence of a terminating character in the string transmitted by arduino.
A read operation using fgets in MATLAB completes/returns only when the terminator character is read.When there is no terminator character in the data being read by fgets, it causes a timeout. The default terminator character for serial object in MATLAB is 'LF' (line feed or new line).
1. In your arduino code, just append the new line character to your string before sending it over serial :
String send_string = "I" + string_R2 + "\n"; % Append the new line/LF character
In your MATLAB code, just to be sure, you could set the Terminator value for the serial object to LF :
%INITIALIZE THE SERIAL PORT
s = serial('com3');
set(s, 'BaudRate', 9600); % set BaudRate to 9600
set(s, 'Parity', 'none'); % set Parity Bit to None
set(s, 'DataBits', 8); % set DataBits to 8
set(s, 'StopBit', 1); % set StopBit to 1
% set terminating character to LF/new line
set(s,'Terminator','LF')
Also in the MATLAB code, instead of waiting for 10 seconds using pause, you could just wait till serial data is available(by querying the BytesAvailable parameter, and then read the data :
%Wait few secs for the Arduino to do things
%pause(10);
while(get(s,'BytesAvailable')==0)
% wait for arduino to send data
end
%receive string from serial
%MATLAB receives the string "I1000"
stringI = fgets(s);
2. Alternatively, if you don't want to modify your arduino code, you could just modify the MATLAB code to use fread to read only the number of bytes of available data without it waiting for the terminating character.
%Wait few secs for the Arduino to do things
%pause(10);
while(get(s,'BytesAvailable')==0)
% wait for arduino to send data
end
%receive string from serial
%MATLAB receives the string "I1000"
%stringI = fgets(s);
stringI = fread(s,get(s,'BytesAvailable'), 'uint8');
  댓글 수: 1
Walter Roberson
Walter Roberson 2018년 12월 18일
instead of modifying the string use Serial.println

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Run on Target Hardware에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by