Communication between Arduino and Matlab Help

Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
1 replies · 4K views
Jonathan_36
Messages
1
Reaction score
1
I am trying to achieve real time plotting of accelerometer data using an arduino, an Xbee, and Matlab. Usually when the Matlab program gets data, it gets something like this:

~ #� ' X: -2 Y: 20 Z: 4080 t: 33232

~ !� ' X: 4 Y: 2 Z: 4066 t: 33255

b~ &� ' X: 1090 Y: 218 Z: 4086 t: 33277

]~ %� ' X: -204 Y: 48 Z: 4084 t: 33300

¢~ $� ' X: 86 Y: 104 Z: 4060 t: 33323

which is fine, and is what I want but there are also times in which I will get data like this:Ï~ %� $ X: 210 Y: 116 Z: 4074 t~ #� $ X: -2 Y: -2 Z: 4074 t: 33684

~ #� $ X: 16 Y: -4 Z: 4084 t: 33707

~ "� $ X: -2 Y: 4 Z: 4064 t: 33729

where I will get an incomplete line of code mashed together with a complete line of code and I am stuck on how to fix this. Is there anything in my code I overlooked or is there something else I should try?

On the arduino side, the code is below:

Code:
#include <Wire.h>
#include "RTClib.h"
#include <Adafruit_MMA8451.h>  //accelerometer
#include <Adafruit_Sensor.h>
#include <SoftwareSerial.h> //for wireless transmission with the xbee

Adafruit_MMA8451 mma = Adafruit_MMA8451();
SoftwareSerial XBee(2, 3);

void setup(void) {
  Serial.begin(57600);
  XBee.begin(57600);
  Serial.println("Here we go!");
 
  #ifdef AVR
    Wire.begin();
  #else
    Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
  #endif

  if (! mma.begin()) {
    Serial.println("Couldnt start");
    while (1);
  }
  Serial.println("MMA8451 found!");
 
  mma.setRange(MMA8451_RANGE_2_G);
  Serial.print("Range = "); Serial.print(2 << mma.getRange()); 
  Serial.println("G");
 
}

void loop() {

  XBee.write(Serial.read());
  // Read the 'raw' data in 14-bit counts
  mma.read();
 
  Serial.print("X:\t"); Serial.print(mma.x);
  Serial.print("\tY:\t"); Serial.print(mma.y);
  Serial.print("\tZ:\t"); Serial.print(mma.z);
  Serial.print("\t");
  Serial.print("t:\t"); Serial.print(millis());
  Serial.println();
 
delay(20);
}

On the Matlab side, I simplified my code down to this:

Code:
close all
clear all
clc

%% Setup

% Clears open COM ports that are already in use by MATLAB
instrreset

% Sets communication channel with the sensor to COM4
s = serial('COM4');

% Sets the baud rate for the connection
% This must be the same baud rate of the XBee transmission
set(s, 'BaudRate', 57600);

% Opens the communication channel with the sensor
fopen(s);

%% Initializing Variables and setting up data matrix

% Initializing variables
Number_of_Samples = 500;
i = 1;
j = 1;
k = 1;
l = 1;
x = [];
y = [];
z = [];
time = [];
t_arduino = [];
t_difference = [];

data = [];

%%

% Startup messages
fprintf('Setup complete. \nStarting data collection.\n');

figure();
hold on
grid on
axis auto
xlabel('Time (seconds)');
ylabel('x, y, and z 4096/g');
title('Real Time Accelerometer Data');

t1 = clock;
%%

while i <= Number_of_Samples
   
    Line = fgets(s)
    
    Raw_Data = sscanf(Line, '%*s%f');
   
    Size = size(Raw_Data);
   
    for j = 1:Size(1)
       
        %Gets placed in the x-data column
        if mod(j, 4) == 1
            data(l,k) = Raw_Data(j);
            x_temp = Raw_Data(j);
            x = [x x_temp];
            k = k + 1;
        end
       
        %Gets placed in the y-data column
        if mod(j, 4) == 2
            data(l,k) = Raw_Data(j);
            y_temp = Raw_Data(j);
            y = [y y_temp];
            k = k + 1;
        end
       
        %Gets placed in the z-data column
        if mod(j, 4) == 3
            data(l,k) = Raw_Data(j);
            z_temp = Raw_Data(j);
            z = [z z_temp];
            k = k + 1;
        end
       
        %Gets placed in the time column
        if mod(j, 4) == 0
            data(l,k) = Raw_Data(j);
            t_arduino_temp = Raw_Data(j);
            t_arduino = [t_arduino t_arduino_temp];
            t2 = clock;
            t_temp = etime(t2,t1);
            time = [time t_temp];
            l = l + 1;
            k = 1;
        end
   
    end
   
     plot(time, x, 'r', time, y, 'k', time, z, 'b')
     legend('x', 'y', 'z')
   
    if mod(i, 50) == 0
        drawnow
        %fprintf('Collected %d samples. \n', i)
    end
   
    i = i + 1;
   
end

%% Finishing up

% Housekeeping - close and clean up all data streams
fclose(s);
fclose(dat);
delete(s);
clear s;
 
  • Like
Likes   Reactions: berkeman
on Phys.org
I'd get rid of the X,Y,Z,T stuff. Its unneeded as you know the order of your data.

And I'd get rid of the \t characters as also unneeded and use spaces or if its better in your MATLAB code use commas as in comma separated values (CSV) file format.

Also I'd combine the four prints into one print line call.