2

I am now trying to establish the serial communication between Arduino and Matlab. The script is very simple:

  1. Matlab send a number named as i to Arduino;

  2. Arduino receive this i, then send it back to Matlab;

Repeat step 1&2 for 10 times, i.e., Matlab sends 1,2,...,10 to Arduino, then receive the 1,2,...,10 from Arduino. However, Matlab only get back 3,4,...,10, while the first i=1 and i=2 are lost (I have already made the inputbuffersize=200 now, still not right).

Hereby is the code from Matlab:

clc,clear;
s=serial('COM16','BaudRate',9600); 
s.InputBufferSize = 200;    
fopen(s);
a=10;
rx = zeros(1, a); % rx is used to store the data send back by Arduino
ry = zeros(1, a); % ry is just helping me to see what happens in Serial
for i = 1:1:a
  fwrite(s, i); % Start to write the value "i" through serial to Arduino
  pause(0.5) % if no pause, the result is worse than now
  ry(i) = s.BytesAvailable; % check how many data are there in the Buffer
  if s.BytesAvailable>0
      rx(i) = fread(s, s.BytesAvailable); % Record the data send by Arduino
  end
end
fclose(s);

And the Arduino Code:

char ibyte;
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if(Serial.available()>0)
  {
    ibyte=Serial.read();
    Serial.write(ibyte);
  }
}

My reference link is: http://robocv.blogspot.com/2012/01/serial-communication-between-arduino.html

7
  • I got rx= [0,0,3,4,5,6,7,8,9,10], which should be [1,2,3,4,5,6,7,8,9,10]... Commented Aug 7, 2018 at 14:12
  • I tried "adding the timeout of s to be 30 seconds", not working-->system time out; I tried "deleting the s.BytesAvilable loop", not working-->system time out. I tried "adding data precision to be unit8", the first 2 numbers are lost as before. Commented Aug 7, 2018 at 15:15
  • 1
    In the post you are referencing your code on, as Gnovice has suggested it says fwrite(s, i, 'uint8', 'sync'); why did you not use that version? Commented Aug 7, 2018 at 15:21
  • uint8, not unit8, sorry. But, still, not working. Sad face. Commented Aug 7, 2018 at 15:26
  • 2
    "Notice the 2.5 seconds of delay that I have added in setup(). This is because everytime Matlab opens communication with Arduino, the Arduino reboots. When it does so, it conducts some mysterious dialogue with the operating system of the computer. In this sensitive time, if it gets flooded by data coming in from Matlab, it might behave unpredictably. So it is always safe to allow the Arduino to settle down and be comfortable before asking it to communicate with your application. " From your link. Go read it ;) Commented Aug 7, 2018 at 15:48

2 Answers 2

2

When you open the serial connection, the Arduino resets itself and the bootloader waits for potential sketch upload. This adds some delay before the sketch actually runs.

Add a pause after you open the serial connection.

fopen(s);
pause(3);

There are other options:

  1. Make the Arduino to announce when it's booted up, by sending something to the PC. For example you wait until the Arduino sends an S.

  2. I am not sure if this is possible with MATLAB, but if you disable the serial's DTR pin, the Arduino won't auto reset.

  3. Burn the code directly with the programmer, so the there is no bootloader which waits at boot. But this also prevents you from uploading the sketch via the USB.

  4. A hardware solution to prevent auto reset. But this prevents the necessary reboot during the sketch uploading, so you have to time the reset manually.

Sign up to request clarification or add additional context in comments.

1 Comment

You are right, I think both Matlab and Arduino needs their "cool down" time. I add 2500 ms delay in Arduino and 5 seconds pause in Matlab, them it works. Both cool down time is necessary, otherweise, not working.
2

The link you provide clearly notes that delay(2500); needs to be added to the Arduino setup() code to allow time for rebooting, during which the device may "behave unpredictably" (like dropping sent data?). You may need to pause the MATLAB code to accommodate for that as well, such as adding a pause(2.5) to your code after you open the serial connection (unless the fopen step already waits for the Arduino setup() to finish).

Regarding your MATLAB code, one problem is that your code is set up so that it could possibly move ahead with sending more data before it has a chance to get the prior response. In addition, you should specify the precision of the data you're sending, like 'uint8' for an unsigned 8-bit integer or 'double' for a double-precision number (as is your case).

What you probably want to do is just call fread without checking BytesAvailable first, since fread will block until it receives all of the data specified by the size argument (1 in this case). Only after receiving will your loop move on to the next iteration/message:

for i = 1:1:a
  fwrite(s, i, 'double');
  rx(i) = fread(s, 1, 'double');
end

You could also try using only uint8 data:

rx = zeros(1, a, 'uint8');
for i = 1:1:a
  fwrite(s, uint8(i), 'uint8');
  rx(i) = fread(s, 1, 'uint8');
end

5 Comments

I have tried your suggestion, then the matlab feedback as "The specified amount of data was not returned within the Timeout period." To me, it is not a delay, it is a missing. Number 1 and number 2 are lost, instead of delayed~
@ZhengHu have you tried just for testing, to increase that Timeout period?
@ZhengHu: I think the issue also has to do with your data precision, as addressed in my updated answer.
@AnderBiguri I have tried to increase the timeout to be 30 seconds by "s.Timeout=30". But it make no difference.
@gnovice Because Arduino is using Serial.write() function to feedback, so the double-type(8 Byte) doesn't work for me. Then I tried 'unit8' (1 Byte) instead of 'double', but the same problem->the first 2 number are lost. But your suggestion worth trying, thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.