Arduino serial read bug
17 views (last 30 days)
Show older comments
What I want to do is to sample an analog voltage from an Arduino pin (0 to 5 V, read as integer values from 0 to 1024), and transmit these samples to Matlab to be plotted. The code below is for the Arduino, it sets up the serial port and then in the loop it reads the voltage from pin 1, sends it to the serial port using "Serial.println", pauses and then keeps repeating this. The sample rate is set by the pause length.
int analogPin = 1; // Analog read pin. This is the e.g. photodiode input
int result;
int sample = 100; // Sampling period (ms)
int Baud = 9600; // Serial baud rate
void setup() {
pinMode(analogPin,INPUT);
Serial.begin(Baud); // Setup serial port
delay(1000); // 1 sec delay
}
void loop() {
result = analogRead(analogPin); // read the analog pin
Serial.println(result);
delay (sample);
}
The following Matlab code configures and opens the serial port, and reads the serial port 100 times and saves these sample values to "y". The results are then plotted.
clear all
clc
baud = 9600;
arduino=serial('COM3','BaudRate',baud);
fopen(arduino);
x=linspace(1,100);
y=zeros(1,100);
for i=1:length(x)
y(i) = fscanf(arduino,'%d');
end
fclose(arduino);
disp('making plot..')
plot(x,y);
When I have a relatively long delay between sampling the pin (say, 100 ms), everything works perfectly. I switch the input to pin 1 between the 3.3 V and 5 V pins on the Arduino, and the correct values are plotted in Matlab. The problem I encounter is when I decrease the sampling rate (to, say 1 ms). I get the following error:
Warning: Unsuccessful read: Matching failure in format.. In an assignment A(I) = B, the number of elements in B and I must be the same. Error in Testexample (line 12) y(i) = fscanf(arduino,'%d');
I guess I'm having a problem with reading the serial data, either Matlab is reading in more than one value, or there's no value to read, and the error occurs because the array y(i) will only accept one entry per column? The data looks fine on the Arduino serial monitor, it looks the same there regardless of the sampling rate.
I don't really know how to troubleshoot this further, so any pointers would be appreciated. Thanks!
2 Comments
Answers (3)
Madhu Govindarajan
on 8 Oct 2015
If you are using one of the latest releases of MATLAB, try using the support package for the same - http://www.mathworks.com/hardware-support/arduino-matlab.html
0 Comments
Jonathan
on 9 Oct 2015
3 Comments
Walter Roberson
on 25 Mar 2016
Edited: Walter Roberson
on 25 Mar 2016
%d means parse a decimal number (that is, an integer base 10)
fread with 'float' is a binary read.
Use %f format or %g format to format floating point output as string, and use %f format to read floating point input as string.
Kiki
on 29 Mar 2016
Hi
So if I use print() in my arduino code, I should use %f in my matlab code as follows to read it, right?
y(i) = fscanf(arduino,'%f');
Thank you.
Walter Roberson
on 9 Oct 2015
USB is not a dedicated channel. USB is a system whee a master device goes around polling the attached devices asking each one in turn if they have any data to send. If they do and it is a relatively small amount of data they might reply with the data, but if it is more data they they are just to reply Yes and the master will get back to them when there is time for them to send the data.
Because of this behaviour, when data is ready to send, it cannot just be sent: the device has to wait for the master to tell it to go ahead.
In documents I read a few years ago but am having difficulty locating now, I found that furthermore, for serial-port emulating devices, USB is designed to wait until either a complete packet is full or else that no data has been received for a time before it will release the packet. This is good for efficient use of shared bandwidth but it is not good for latency. If your bytes are available more slowly than the wait for data then you don't really notice much (provided that your data is not too time sensitive), but after a point you get stuck: before the end of the wait period you get another byte and since the packet isn't full yet the timer restarts.... only to be interrupted by the next packet. And so on, until the packet is full. This can end up with longer latency than if the data rate was slower. But, hey, it is efficient use of the bandwidth and that is what is important, right?
So... you might not get data for a while. And you might time-out if you are not set to handle the worst-case of the timer being reset just as it was due to expire, over and over again. And even if that does not happen, batches of bytes arrive rather than single bytes and your code might not expect that...
Serial over USB is... Bovine Growth Hormone... for data acquisition unless both sides know how to trigger immediate data sending (which requires talking to the master device, and which MATLAB does not provide an interface for.)
0 Comments
See Also
Categories
Find more on MATLAB Support Package for Arduino Hardware in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!