0
votes

I'm trying to send data from my Arduino Leonardo to Matlab then plot it. I've tried passing a sine wave to the analog inputs and I was able to see it on the serial plotter. The problem is that, whenever I send the data to Matlab and plot it, the plot is no longer a sine wave.

Here is my Arduino code, I've adjusted it with the help of of this link to sample at 1kHz, which didn't affect the serial plotter results that much.`

#define INTERVAL_LENGTH_US 1000UL

unsigned long previousMicros;
#define FASTADC 1
int recValue;
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
double t = 0;


void setup() {
  int start ;
  int i ;

#if FASTADC
  // set prescale to 16
  sbi(ADCSRA, ADPS2) ;
  cbi(ADCSRA, ADPS1) ;
  cbi(ADCSRA, ADPS0) ;
#endif

  Serial.begin(115200) ;
  while (1)
  {
    if (Serial.available() > 0)
    {
      recValue = Serial.read();

      if  (recValue == 1)            // If use will send value 1 from MATLAB
      { //delay(10);

        Serial.println("g");
        break;
      }

    }
  }


  void loop()
  {
    unsigned long currentMicros = micros();

    if ((currentMicros - previousMicros) >= INTERVAL_LENGTH_US)
    {
      previousMicros += INTERVAL_LENGTH_US;

      int val_a0 = analogRead(A0);
      int val_a1 = analogRead(A1);
      int val_a2 = analogRead(A2);
      int val_a3 = analogRead(A3);



      Serial.println(val_a0);


      Serial.println(val_a1);

      Serial.println(val_a2);


      Serial.println(val_a3);

    }
  }

EDIT: I changed the board to an UNO one (doesn't use virtual communication port) and I managed to transfer it. But when I was plotting it in realtime, I onle managed to plot for a short time (700 samples). I know that the Arduino is sending the sine wave contiuously, its just that in matlab, I only get a portion of it. Here is a screenshot of what I mean:

Recieved sine

The code I used in Matlab to receive and plot it is the following:

        clear all;
    s = serial('COM4', 'BaudRate', 250000); % setup comport
    fopen(s);
    t=[0]; v1=[0]; v2=[0];v2=[0];v3=[0]; v4=[0];                            % same as in Arduino IDE
    n=1;h1=0; h2=0; h3=0; h4=0; base=0.0; x=[];  reply = '1';

    % signalling to Arduino to start reading inputs
    servalue= input('Enter the value 1 to start reading :');
    pause(1);tic;
    fprintf(s,servalue);
    %Arduino will send an acknowledgment
    reply = fgetl(s);
    if(reply~='g')
        disp('fail')
    end
    %%%%%%%%%%%%%%%%%%setting the plots%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
    figure; subplot(411) ;
    h1 = plot( v1, 'r-');
    %animatedline(nan,nan); % Save handle to the line
    title('Channel 1');
    ylabel('Amplitude(V)');

    subplot(412); h2= plot( v2, 'r-');
    %animatedline(nan,nan); % Save handle to the line
    title('Channel 2');
    ylabel('Amplitude(V)');


    subplot(413); h3= plot( v3, 'r-');
    %animatedline(nan,nan); % Save handle to the line
    title('Channel 3');
    ylabel('Amplitude(V)');

    subplot(414); h4= plot( v4, 'r-');
    %animatedline(nan,nan); % Save handle to the line
    title('Channel 4');
    xlabel('Time (seconds)');
    ylabel('Amplitude(V)');
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5

    while(toc<50)

        v1 = [v1, str2double(fgetl(s))*(5.0 / 1023.0)];
        v2 = [v2, str2double(fgetl(s))*(5.0 / 1023.0)];
        v3 = [v3, str2double(fgetl(s))*(5.0 / 1023.0)];
        v4 = [v4,str2double(fgetl(s))*(5.0 / 1023.0)];

        %% %%%%%%%updating plots%%%%%%%%%%%%%%%%%%

        set(h1,  'ydata', v1); % Update plot
        set(h2,  'ydata', v2); % Update plot
        set(h3,  'ydata', v3); % Update plot
        set(h4,  'ydata', v4); % Update plot
        drawnow;

        n=n+1;

    end
    fclose(s);

Here is the response of the 4 channels: 4 channels' response

1
What are the 5 possible values that are being plot on the Excel graph? - Noel Segura Meraz
Are you sending and receiving 1 or 4 signals at the same time? - Noel Segura Meraz
4, I commented the other three earlier because I wanted to test a single channel at first, I forgot to edit that out in the question, it's all fixed now. - Isra
What are you sending on the other 3 lines when you send the sine wave on the val_a1? because it is possible that you are desincronizing due to dropped data and mixing the 4 channels - Noel Segura Meraz
ch0 is connected to a sine wave, ch1 s connected to a square wave, ch3, and 4 are grounded. Ch2's response is exactly like ch1's response - Isra

1 Answers

0
votes

Looks like your problem is that some data is dropped and that de-synchronize your sending and receiving of data.

Ideally you want to send a stream like:

...Ch1-Ch2-Ch3-Ch4-Ch1-Ch2-Ch3-Ch4-Ch1-Ch2-Ch3-Ch4-Ch1-Ch2-Ch3-Ch4...

And receive it in Matlab like:

V1    V2    V3    V4
Ch1 - Ch2 - Ch3 - Ch4
Ch1 - Ch2 - Ch3 - Ch4
Ch1 - Ch2 - Ch3 - Ch4
Ch1 - Ch2 - Ch3 - Ch4

But, if there is some dropped data for whatever reason, then your channels will get mixed:

Your stream will look something like:

...Ch1-Ch2-Ch3-Ch4-Ch1-Ch2- -Ch4-Ch1-Ch2-Ch3- -Ch1-Ch2-Ch3-Ch4-Ch1-Ch2...

So your program in Matlab will accommodate that data as

V1    V2    V3    V4
Ch1 - Ch2 - Ch3 - Ch4
Ch1 - Ch2 - Ch4 - Ch1
Ch2 - Ch3 - Ch1 - Ch2
Ch3 - Ch4 - Ch1 - Ch2

As you can see, it works for a while, but when data is dropped, then all coordination is lost.

There are several of ways you can solve this. Search for "synchronizing serial communications" and you'll find several methods.

In you case I would suggest to send all channels separated by commas in one single line, and then separate them in matlab. In the Arduino side:

  Serial.print(val_a0);
  Serial.print(',');
  Serial.print(val_a1);
  Serial.print(',');
  Serial.print(val_a2);
  Serial.print(',');
  Serial.println(val_a3);

Then on the Matlab side

data=strsplit(fgetl(s),',');

if lenght(data)==4
    v1 = [v1, str2double(data(1))*(5.0 / 1023.0)];
    v2 = [v2, str2double(data(2))*(5.0 / 1023.0)];
    v3 = [v3, str2double(data(3))*(5.0 / 1023.0)];
    v4 = [v4, str2double(data(4))*(5.0 / 1023.0)];
end

Be careful that this will only fix the synchronization, but might introduce other errors if partial data is received. You can handle that with some try-catch statements