Call Arduino SPI functions with MATLAB - matlab

I have successfully connected MATLAB with my Arduino. So far, I have only sent simple tasks to the Arduino such as digitalWrite and such.
The code I have been using is as follows:
%-- connect to the board
a = arduino('COM9')
%-- specify pin mode
a.pinMode(9,'output');
%-- write 0 (off) to pin 9
a.digitalWrite(9,0);
%-- dummy variable
on = false;
%-- simple loop to make LED flash 5 times
for m in 1:5
if on
a.digitalWrite(9,0); % turn LED off
on = false;
else
a.digitalWrite(9,1); % turn LED on
on = true;
end
%-- close session
delete(a)
Now that this basic test successfully passed, I wanted to get the SPI Arduino library to work with MATLAB. Is it possible to call a function from the Arduino SPI library in my MATLAB code? Specifically, I want to get SPI.begin(); and SPI.end(); to work from MATLAB, but a.SPI.begin() is not working. Is there some step I am missing?
To get the SPI library into an Arduino program, one must use #include <SPI.h>, but how can we make sure MATLAB knows all of the functions available in the SPI library? Hopefully it is not a problem that the Arduino SPI Library code is written in a different language than what MATLAB files are written in.
References:
MATLAB Support Package for Arduino (aka ArduinoIO Package)
Arduino SPI Library

The library "ArduinoIO" does not support SPI.
That library is just a serial port listener, and every matlab/arduino instruction send a code by serial, that is readed in the sketch on the arduino, translated in the corresponding arduino's instruction, and then executed.
You can create your own block that send some your-choise-spi-command, you'll also have to edit the arduino's sketch to execure the corrisponding SPI command. But you'll have to understand how the library works, change it's code, and so on.
It is way more faster (in execution speed, as serial comunication really is slow, and coding time) to code a "specialized" arduino sketch, that send back to Serial just the value you need, and then read serial and to pc-side computation.

To communicate with SPI device using Matlab support package you can use the following code:
a = arduino();
Spi_Device = spidev(a, 'D5'); % D5 is the pin number that you want to use for chip select
writeRead(Spi_Device,[hex2dec('00'), 100]); % 100 is the value that you want to send to the device
% When you done clear the spi object
clear Spi_Device

The Legacy MATLAB and Simulink Support for Arduino is no longer supported. I would recommend using the MATLAB Support Package for Arduino Hardware as that has built-in support for basic SPI communication.
There are getting started type of examples that comes with the support package and one of them shows how to use SPI.
Disclaimer: Even though I work for MathWorks, these posts are based on my experience with the software as a user. For actual Technical Support, please contact Mathworks' TS.

Related

BMI160 & STM32 Strange Behaviour - Sensor Succesfully Inits but Accel and Gyro Reads are always zero

I am trying to use the BMI160 sensor with my STM32G474 Nucleo board. I am working over I2C. I wrote the Read - Write and DelayUS functions.
I successfully init the sensor. It returns 0 as "rslt", which means everything is fine according to this library. After that, when I configure Accel and Gyro, rslt still returns 0.
But I am constantly reading 0 from gyro and accel. Also, sometimes I get -7 error after configuring Accel and Gyro. I guess my ODR/BW settings for Accel and Gyro are not working. How can I set the correct ODR/BW and datarate?
I'm posting the code I'm using, below. In addition to the standard BMI160 library, I write two more codes to be able to use library:
common_porting = Holds I2C Read - Write and DelayUs functions
bmi160_wrapper = The code I wrote to use Bosch's standard library with common_porting. In the Main() function, I call the BMI160_init() function directly in this code, for example, to initialize the BMI160.

MATLAB and Arudino, set registers (PWM)

I am using an Arduino MEGA with MATLAB for the first time to try and control a servo motor, the issue is that the default PWM frequency for the pin I am trying to use is at 976Hz, while I need it to be around 50Hz. I found code for changing the timer 0 B register that affects this frequency but only for use in the Arudino IDE.
So basically, I need to send the following command to the Arduino:
TCCR0B = TCCR0B & B11111000 | B00000101;
Does anyone know how to do this while using the Arduino MEGA through MATLAB? Is there not a way to have straight up Arudino code in the .m file through some function/syntax? Or is there another way to manipulate the TCCR0B register via MATLAB? I know I could do this on the Arduino IDE but I really need to use MATLAB for the rest of this project.
Thank you for your time.

Basic networking with Matlab Coder

I'm trying to get very basic network functionality with Matlab Coder (I need to turn it into C code). However, all the network classes and objects I try arn't supported by Coder. It seems unreasonable that Matlab would completely neglect networking entirely with this tool. Is there some method of sending data over a network that DOES work with coder?
I'd prefer TCP, but UDP or anything else that will actually send/receive data will work, as long as it is compatible with Coder.
This answer assumes that the DSP System Toolbox is not available. If it is, the System Objects dsp.UDPSender and dsp.UDPReceiver may be considered.
Since the final goal is to generate C code, and because network I/O is usually done via a library, a good approach would be to integrate external C code that does the network I/O into your MATLAB Code. The basic way to call an external C function is using coder.ceval and the process is explained here.
Recommended Steps
Write C(++) functions implementing the behaviour you need or find a C library providing the necessary functionality. Assume we implement the function externalUDPSend in the files externalUDPSend.h/.c.
Write one or more MATLAB functions that call your C(++) functions using coder.ceval as shown in the linked documentation. These will serve as a wrapper around your external code, and will expose the C(++) code to MATLAB. Something like callfoo in the linked example will work:
function y = useExternalUDP(x)
%#codegen
if coder.target('MATLAB')
% Running in MATLAB. Use standard MATLAB
% network I/O code here
...
else
% Generating code. Call external code/library
% Include header for external code
coder.cinclude('externalUDPSend.h');
% Set the type of the output. Assume double scalar
% Change the RHS to match the return type
y = 0;
y = coder.ceval('externalUDPSend',x,numel(x));
end
Develop your project. Call the wrapper function(s), which will work in MATLAB and in the generated code because of the use of coder.target.
Generate a MEX function using something like:
codegen useExternalUDP -config:mex externalUDPSend.c -args ...
The generated MEX function serves as the MATLAB interface to your custom code so there is no need to hand write a MEX interface. MATLAB Coder will generate all of MEX interfacing logic for you. Then test that MEX function in MATLAB. Testing the MEX function is important because runtime errors like out of bounds indexing, using features not supported for code generation, etc. can be detected and reported in MEX. These checks are removed from generated standalone code.
Generate standalone code and either let MATLAB Coder compile it to a library or deploy the code to an external IDE and compile it there.
Integrating External Libraries/Encapsulating Dependencies
Note that you may also need to link in libraries if you choose to use an existing network I/O library, or you may need to modify the build of the generated code. You can either use coder.updateBuildInfo or coder.ExternalDependency to achieve this in your MATLAB Code.
Further Reading
The file reading example shows some more advanced custom code integration tools such as coder.ref, coder.opaque, and dealing with C strings from MATLAB code when calling external code. Note that the MATLAB functions fprintf and fread are supported for code generation so this example is meant to be instructive rather than a necessity for doing file I/O.
If you have the DSP System Toolbox, the System Objects dsp.UDPSender and dsp.UDPReceiver are supported for code generation since they are listed in the comprehensive list of supported functions.
The code generated from them relies on prebuilt libraries shipped with MATLAB and will run on desktop platforms compatible with those libraries. See the documentation for the UDP Receive block for more details.

Simulink external mode and Arduino Mega 2560

I'm stuck with Simulink Arduino Target in MATLAB 2012a. Simulink can compile my model and download it to the hardware. It seems to work, but when I do have a scope in my simulation, activating the external mode (for tuning my model and tracing the values) causes Simulink to crash ("Segmentation Violation", but the most time it just hangs without any error). It crashes the same way if I disconnect the usb-cable during external mode.
I'm using the Arduino Mega 2560 R3 Hardware, Matlab 2012b on Win 7 64 bit and Win XP.
Any help is welcome, the matlab forum doesn't give any useful answer (at least so far).
I could reproduce the same error you've described in your post when using a sample time in the Analog Input block which was different to the sample time in the Simulation Settings pane. In other words, there is a good chance that one of the Arduino blocks has a different sample time to the global sample timing --- and this is an issue for the Arduino support package.
Normally (in xPC Target) you just get an error message if the sample time does not make sense (non multiple of the global or faster) but a slower multiple is not an issue. Here I've found that the input block needed the same sampling as the global model to work.
(Matlab 2012b, Win 7 x64, Arduino Mega 2560 R3, external mode)
Gergely

Unable Send Data From Matlab To DSPIC 30f4011

I am facing some problems while trying to send data from Matlab To DSPIC30f4011 through USB to UART Converter. Here is my code:
function comparison()
global x1 y1
s=serial('COM3');
set(s,'BaudRate',9600);
fopen(s);
fprintf(s,'2');
out=fscanf(s);
fclose(s);
But my circuit board is unable to receive the data. How can I solve this problem?
Receive:
I always had problems receiving data from a serial port, so I used a mex file GetSerialData.cpp, but right now I can't figure were came from.
Send:
To send data correctly it is really important that you got the right baud rate and COM-port. You could check the com-port in your windows device manager. Mine shows up in the (COM & LPT) group as USB Serial Port (COM7).
The baud rate depends on your DSPIC30F4011 device, which you probably also have to configure.