Problem with Arduino and MATLAB

Hi guys,
I have a little problem with the SPI transfer. I wrote a code for managing a 16-bit DAC (AD5570) in order to otain a certain voltage output (chosen by the user).
Here there is the code:

#include <SPI.h>


float DACR;
unsigned int Din;                 //input signal
const int V_ref = 5;              //voltage refernce for DAC
long tot_level = 65535;           //(2^16)-1 levels for the output

const int pinSYNC_DAC = 52;       // pin CS

void setup() {
  
  pinMode(pinSYNC_DAC, OUTPUT);
  SPI.begin(pinSYNC_DAC);
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));
  Serial.begin(115200);

}



void loop() {
  
   if (Serial.available() != 0) {
    DACR = Serial.parseFloat() ;
    Serial.print("Voltage selected: ");
    Serial.println(DACR, DEC);
    Din = ((DACR + 2 * V_ref) * tot_level) / (4 * V_ref);
    Serial.println(Din, DEC);
    if (Din >= tot_level) {
      Din = tot_level;}
    byte msg2 = (byte)Din;
    byte msg1 = (byte)(Din >> 8);
    SPI.transfer(pinSYNC_DAC, msg1, SPI_CONTINUE);
    SPI.transfer(pinSYNC_DAC, msg2, SPI_LAST);

    delay(4000);


  }
}

The code is working properly. I had implemented a MATLAB GUI to manage the device and at the moment there is just an edit text and a pushbutton. In the edit text field the user will choose the voltage and the pushbutton will be used to update the voltage to the DAC. Here i have reported the code in MATLAB:
pushbotton

Din=1;
V_ref=5;
tot_level=65535;
Din = ((str2double(get(handles.choose_voltage,'String')) + 2*V_ref)*tot_level)/(4*V_ref);
fprintf(handles.s,'%f\n',Din);

where handles.choose_voltage is the tag name of the edit text field and handles.s is for enabling the serial communication between arduino and MATLAB.
Tha problem is that if i print the variable called “Din” on the serial monitor, it looks correct, but i can’t perform the SPI transfer more.

I simplified the Arduino code like this:

#include <SPI.h>


unsigned int DACR;
long tot_level = 65535;           //(2^16)-1 levels for the output

const int pinSYNC_DAC = 52;       // pin CS

void setup() {
 
 pinMode(pinSYNC_DAC, OUTPUT);
 SPI.begin(pinSYNC_DAC);
 SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));
 Serial.begin(115200);

}



void loop() {
 
  if (Serial.available() != 0) {
   DACR = Serial.parseInt() ;
   if (DACR >= tot_level) {
     DACR = tot_level;}
   byte msg2 = (byte)DACR;
   byte msg1 = (byte)(DACR >> 8);
   SPI.transfer(pinSYNC_DAC, msg1, SPI_CONTINUE);
   SPI.transfer(pinSYNC_DAC, msg2, SPI_LAST);

   delay(4000);


 }
}

I really don’t know how to solve the problem.
Thank you for you attention

I have a little problem with the SPI transfer.

That appears to have nothing to do with your thread title.

You failed to explain what your little problem is.

You need to do some research to determine what SPI.beginTransaction() actually does, and what SPI.endTransaction() does (and you need to explain why you don't call it and how you expect any SPI communication to actually happen when you don't call it).

The problem is that when i run the code from arduino IDE and i set my voltage in the serial monitor, the SPI transfer works properly and i got my voltage at the output of the DAC.

But if i run the same code setting the voltage from MATLAB, the SPI doesn't work and seems that he transfers only two bytes of zeroes.

Thank you again for your attention

But if i run the same code setting the voltage from MATLAB, the SPI doesn't work and seems that he transfers only two bytes of zeroes.

Then, the problem is NOT with SPI or the DAC. It is with the serial transfer of data between MATLAB and the Arduino.

Though I do not for a minute believe that the code you posted actually works.

Sending data from the Serial Monitor application to the Arduino involves text. Who knows what your MATLAB program is sending.

Thank you, soory but it's my first program.

In the callback field of my pusbotton i read the value inside the "edit text" field in a 'String' format. Then i make a conversion from strin to double and then i print on the serial monitor using fprintf. This is my callback function:

function update_voltage_Callback(hObject, eventdata, handles)
Code=1;
V_ref=5;
tot_level=65535;
Code = ((str2double(get(handles.choose_voltage,'String')) + 2*V_ref)*tot_level)/(4*V_ref);
fprintf(handles.s,'%f\n',Code);

Then i used the Serial.parseInt() to read from the serial monitor. But probably i made a big mistake with the type of variables.

Thank you and sorry again.

You sent a float, and used parseInt() to read it. I see.

No, wait, no I don't.

Sorry, my mistake.

But even if i replace the ‘%f’ with a ‘%d’ the code is not working. Looking to the output, the code just transfer 16 ‘0’ bits.

Thank you for you attention.

Do you KNOW what the value is, in Matlab, that is being sent, as a string?

Can you read data, in Matlab, sent by the Arduino? If so, what did the Arduino actually get?

Yes, i try to explain it better. So, for example i tape the value '1' inside the edit box text. According to the calculation reported in the callback function, the value that i need to use inside arduino is '36044' (it's a fraction of the total 2^16 levels in which the output can be represented with my 16-bit DAC). This value needs to be converted in two bytes and then ther's the SPI.transfer().

I don't know why but i read the correct value only if i use the '%f' inside the callback function (instead of '%d') and the Serial.parseInt() inside the arduino code and this is the first problem. If i use the 'disp()' instruction in MATLAB to see wht is the variable call 'Code' in my callback function, it returns: 3.6044e+04.

After that if i check the serial monitor to see what MATLAB printed, i see the correct value:

36044

That means two byte:

10001100 11001100

So i thought that the problem was in the SPI transfer function because the value were correct.

Thank you again.

Than i have the SPI.transfer() but probably i made a mistake in

I don't know why but i read the correct value only if i use the '%f' inside the callback function

Because the value is a float.

and the Serial.parseInt() inside the arduino code

But that is stupid since you are not sending an int. Send a damned int if you are going to use parseInt. Use parseFloat() if you are going to send a float.

Quit being stubborn.

Yes, you have a problem with how you are sending the data using SPI, but you keep insisting that you don't.

Ok, you are completely right. In fact i'm trying to send a '%f' float in MATLAB of the same value as before. Like the preavious post, MATLAB gives me the value with the 'disp()' function:

3.6044e+04

If i try to read this value with a Serial.parseFloat() instruction in the arduino code, the serial monitor prints this value:

1684.5114746094

That is completely different from the value that i would like to recive. Why there's no compatibility between these two values?

Thank you and sorry again

If I’m understanding, you have MATLAB AND the Serial Monitor application talking to the SAME serial port? That just might be the source of your problems. ONE application on each end of the serial port works. More than one and no one guarantees anything.

Can MATLAB read from the serial port? I know that it CAN, but why are you not using that capability?

Yes, i have both of them on the same serial port. While the port is opened from MATLAB i can't read the serial monitor application. To read this one i had to made a infinite cycle like

while(1==1){ Serial.println(DACR,DEC); }

In this way i can check what is printed on the serial monitor application after closing the serial port. Should i use two serial ports?

My aim is to give to arduino this float value, so how can i use the capability of MATLAB to read the serial port? MATLAB should write on the serial port and the arduino should read the value printed. But maybe i'm wrong.

Really thank you

so how can i use the capability of MATLAB to read the serial port?

I don't know. You're the expert on MATLAB.

My aim is to give to arduino this float value

Why not store the float value in an int, send the int, and use parseInt(), since that seemed to be getting the right value across (though I'm not completely convinced that that is the case)?

MATLAB should write on the serial port and the arduino should read the value printed.

Yes, and the Arduino should be able to write on the serial port and expect that MATLAB can read the value printed.

If i use the %d and then a serial.parseInt to read that value, my arduino read just the value ‘3’ so the first number of the correct value that i would like to send (3.6044e+04).
To check that i add a line in my callback function in MATLAB:

disp(fscanf(handles.s,’%s’));

In this way i can check what the arduino actually prints on the serial port and the result is ‘3’, but i would like to recive a value of ‘36044’.

Thank you

If i use the %d and then a serial.parseInt to read that value, my arduino read just the value '3' so the first number of the correct value that i would like to send (3.6044e+04).

I don't understand why MATLAB can't send 36044 as the string.

I got the right value as i show you in one of my preavious post when i was "mixing" the variable's type (not correctly). Maybe the problem could be related to the serial port? I mean, maybe is not possible to perform a SPI transfer while the port is open. I looked for some informations reagarding this problem but i couldn't find nothing.

Thank you for you help

Forget about MATLAB for the moment. Simply define a long with a value of 36044 (since 36044 won't fit in a signed int).

Get the Arduino so that it can, between beginTransmission() and endTransmission() calls, send 36044 (as 4 bytes) to the device.

Or, use unsigned int, and send two bytes.

Only when that works should you try to integrate the MATLAB stuff.

I’m able to do that with this code:

#include <SPI.h>

int DACR;
unsigned int Din;                 
const int V_ref = 5;              
long tot_level = 65535;            

const int pinSYNC_DAC = 52;       // pin CS

void setup() {
  
  pinMode(pinSYNC_DAC, OUTPUT);
  SPI.begin(pinSYNC_DAC);
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));
  Serial.begin(115200);

}

void loop() {
  if (Serial.available() != 0) {
    DACR = Serial.parseInt() ;
    

    Din = ((DACR + 2 * V_ref) * tot_level) / (4 * V_ref);

    
    if (Din >= tot_level) {
      Din = tot_level;}
    byte msg2 = (byte)Din;
    byte msg1 = (byte)(Din >> 8);


      Serial.println(msg1,BIN);
      Serial.println(msg2,BIN);
    
    
    SPI.transfer(pinSYNC_DAC, msg1, SPI_CONTINUE);
    SPI.transfer(pinSYNC_DAC, msg2, SPI_LAST);
    SPI.endTransaction(); 

    delay(4000);

  }
}

In this way if i tape ‘1’ in the serial monitor, this code will calculate the corresponding unsigned int ‘Din’ then it generates two bytes from Din. Lastly there is the SPI.transfer(), performed for each byte.
This code is working properly, both with a ‘int type for DACR’, than with a float type for that variable.

Thank you!

Does that code work twice? I doubt it.