Strange error in my code?!!
rebecca91
Malta
Hey guys,
Im making use of this code but i keep getting the error: "Warning: Matching failure in format." What does this mean?
[I've got an arduino connected serially to my matlab in which my arduino is giving out 6 continuous outputs to be displayed on a graph].
Can you tell me which part of my code needs to be changed please?
Thanks for any help!!
Im making use of this code but i keep getting the error: "Warning: Matching failure in format." What does this mean?
[I've got an arduino connected serially to my matlab in which my arduino is giving out 6 continuous outputs to be displayed on a graph].
Can you tell me which part of my code needs to be changed please?
SerialPort='com6'; %serial port MaxDeviation = 3; %Maximum Allowable Change from one value to next TimeInterval=0.2; %time interval between each input. loop=120; %count values %%Set up the serial port object s = serial(SerialPort) fopen(s); time =now; voltage = 0; %% Set up the figure figureHandle = figure('NumberTitle','off',... 'Name','Voltage Characteristics',... 'Color',[0 0 0],'Visible','off'); % Set axes axesHandle = axes('Parent',figureHandle,... 'YGrid','on',... 'YColor',[0.9725 0.9725 0.9725],... 'XGrid','on',... 'XColor',[0.9725 0.9725 0.9725],... 'Color',[0 0 0]); hold on; plotHandle = plot(axesHandle,time,voltage,'Marker','.','LineWidth',1,'Color',[0 1 0]); xlim(axesHandle,[min(time) max(time+0.001)]); % Create xlabel xlabel('Time','FontWeight','bold','FontSize',14,'Color',[1 1 0]); % Create ylabel ylabel('Voltage in V','FontWeight','bold','FontSize',14,'Color',[1 1 0]); % Create title title('Real Time Data','FontSize',15,'Color',[1 1 0]); %% Initializing variables voltage(1)=0; time(1)=0; count = 2; k=1; while ~isequal(count,loop) %%Re creating Serial port before timeout k=k+1; if k==25 fclose(s); delete(s); clear s; s = serial('com6'); fopen(s) k=0; end %%Serial data accessing invalues = fscanf(s,'%f'); for k= 1 : length(invalues) voltage(count) = invalues(k); if voltage(count)-voltage(count-1) > MaxDeviation voltage(count) = voltage(count-1) end time(count) = count; count = count + 1; end set(plotHandle,'YData',voltage,'XData',time); pause(TimeInterval);
Thanks for any help!!
0
Comments
%%Serial data accessing
invalues = fscanf(s,'%f');
for k= 1 : length(invalues)
voltage(count) = invalues(k);
if voltage(count)-voltage(count-1) > MaxDeviation
voltage(count) = voltage(count-1)
end
time(count) = count;
count = count + 1;
end
set(plotHandle,'YData',voltage,'XData',time);
pause(TimeInterval);
also, if you type in:
dbstop if error
before running your script, it will drop into the debugger when the error occurs, rather than erroring out. that might allow you to troubleshoot a little more.
Hrmm, this is where it gets confusing then because all my data is coming from 3 gyros and 3 accelerometers so i cant look into a file to see the values they output. Do you know any websites or online topics about serial data sent to matlab to be put in a continuous graph?
I really need some help here :sad2:
What i mean is that i dont have any unexpected values so i dont understand why my matlab gives me that warning :/
If you don't mind my asking, which IMU are you using? I may be able to duplicate your experimental setup.
Im using the Razor 6DOF IMU (http://www.sparkfun.com/products/9431).
How can i do this? Or maybe you know a link which has an example please? As i have no idea what you mean and im so desperate to fix this code!
Yes im using ASCII encoding, so the numbers im seeing are char going into my matlab? How can i do a string-to-number conversion? Or if you know a web page that would be very helpful too.
MathWorks has a help document on serial port I/O that discusses how it works in detail, found here: http://www.mathworks.com/help/techdoc/matlab_external/f62852.html. They show an example of parsing ASCII input with textscan which will probably work for you. However, the examples they show are for a simple query-response problem whereas your problem requires you to continuously parse an incoming bitstream. This is important because they can assume their communication session begins at the beginning of a packet while you can't. You can change your communication session format to a query-response type or develop an algorithm similar to what I mentioned earlier that allows you to detect individual packets within a data stream.
A note on terminology: I incorrectly used "frame" to describe the group of data forming a complete transmission from your Arduino. The correct term for this is "packet" and I'm going to go back and edit my previous post to reflect that. A "frame" is the smallest unit of data that can be transmitted over a serial interface.
The ones that occur to me immediately are query-response, clear-capture-process, and clear-capture-store. There are others out there, just look around for serial read methods on Google and you'll find plenty though not necessarily MATLAB-portable. Quick overview:
Query-response:
The Arduino firmware is designed to loop continuously, checking the serial port for input and sampling the ADC. When a query packet is received, the Arduino sends back a packet containing the current IMU data. MATLAB maintains an input buffer the same size as or slightly larger than the packet size. The buffer then contains a string containing one complete packet which is then parsed. After parse, clear the buffer, process your data, and query Arduino again.
This approach has low latency from MATLAB's point of view but you can't be assured of collecting the data at any particular rate.
Clear-capture-process:
The Arduino firmware is designed to continuously capture, process, and transmit IMU data either at a fixed rate or as fast as possible. MATLAB maintains an input buffer of twice the frame size and continuously checks the buffer for an end-of-packet character. When MATLAB finds one, it clears the buffer and receives frames until another end-of-packet character is found. The buffer is copied to a string variable and cleared. Parse the string variable, process the result, and return to the end-of-packet detection loop.
This approach has higher latency on MATLAB's side and doesn't guarantee the data at any particular rate. However, it's workable when you need the data "as it comes in" and for some reason you can't or don't want to change the device firmware to a query-response type.
Note, if Arduino is configured to transmit at a fixed rate and your processing is fast enough to complete before the next packet begins transmitting, you can skip straight to reading the next packet instead of trying to detect the end of the previous packet (and losing a packet in the process.) In this way, you can collect all the transmitted data and process it in real time. You'll know if this won't work for you because you'll get a packet size mismatch error when you try to parse an incomplete packet (because you missed the first part of it.)
Clear-capture-store:
The Arduino firmware is designed to continuously capture, process, and transmit IMU data at a fixed rate. MATLAB maintains an input buffer of twice the frame size and a string array large enough to contain every packet over your desired sampling period. MATLAB continuously checks the buffer for an end-of-packet character and when found, clears the buffer and receives frames until another end-of-packet character is found. The buffer is copied to the first element of a string array and then cleared. Loop continuously and copy each packet to successive elements of the string array until the sampling period is over. Parse each element of the string array and process the resulting data.
This approach is an offline algorithm which guarantees the data is collected at the rate Arduino sends it because the operations between packets being collected are very fast. However, you don't get to see the results until the end of data collection. This works fine when you only need to collect data for a few seconds on demand but won't work for anything that requires real time response.
I have gone through this web page before already, and i had used the following code to try get the graphs from my arduino instead:
The results above are the same ones i had seen in my arduino when i was looking over the serial monitor, the only difference is that my arduino ran real-time whilst matlab only gave me one sample. Maybe there's something in the code above that needs to be altered and then displayed on a graph? Or should i refer to the code i gave u earlier and add these "packets" that u mentioned?
I counted up the bytes here and including the header ("t[ms] ...") there's 512 bytes. What you're seeing here for val is the complete contents of the input buffer. You've got 8 packets in here, 9 if you count the header packet.
For example, suppose you want to return the cursor and display settings for the oscilloscope. This requires writing the <TT>CURSOR?</TT> and <TT>DISPLAY?</TT> commands to the instrument, and then reading back the results of those commands.
What are these packets you're counting? And what can i do with them?
If you wish i can give you my arduino code, its very short, maybe you'll might understand better than I why my matlab isnt running the way i wish it to be :/
As far as counting packets and frames goes, here's the output you collected: Each character is two bytes because that's how many bytes you need to encode a single ASCII character. The first line is 72 bytes: 36 characters including white spaces and one end-of-line character. Each succeeding line is 54 bytes: 27 characters including white spaces and one end-of-line character. Each line is a packet, so you have one header packet and 8 data packets for a total of 9 packets. The byte count is 72 + 54 * 8 = 504. So not quite the full buffer, but certainly close. There may have been some more white space in there I didn't count. You stored the complete output there as a single string variable.
You're right! No need for that at all here
The reason the byte count is 504 here is because i didnt paste the complete set here so as not to fill up too much space, so u didnt count them wrong, so at least i know my matlab is reading the right amount of bytes.
So the question is, i need to tell matlab to store each data packet in a different string? How can i do that? If u have an example that would be so helpful!
What follows is not intended to be discouraging so please don't take it that way. What you're trying to do here is in a single stroke write a driver for an external instrument, collect data from that instrument, and display the results in an intelligible fashion. What you may want to do is break this program down into chunks and work on each one in order, adding complexity to your problem like layers on an onion. The main tasks here are:
- Reliable serial comms with IMU. This is as simple as being able to get a single, complete packet on-demand from your serial connection.
- Reliable data collection from serial comms. Once you can get one packet, see about collecting several over a period of time and storing them.
- Real-time plotting from data. The MathWorks example is alright but has one serious deficiency that inhibits function at high speeds with large packets. Can you find it?
What you have now is a collection of examples that weren't intended for your application. Each example contains clues that will make your task easier but you still need to understand exactly what each one does to make sense of which parts need to be changed for your problem. As it stands, you can't isolate which features in your software are causing problems.