Do you need to store the files to disk or send them to MATLAB in real-time or both?
Write File in a real-time manner
giuliomoro If you have suggestions for both scenarios, it would be better. Thanks!
- Edited
Here is one hint for sending real-time data to MATLAB:
https://www.mathworks.com/help/xpc/real-time-udp.html
Bela can do UDP. Create a UDP client or server on the Bela in an AuxiliaryTask. One example of simplest UDP client/server I found with Google -- lots of hits, so lots of information for doing UDP with C on Linux:
https://stackoverflow.com/questions/35568996/socket-programming-udp-client-server-in-c
(first response with simple basic client and server examples are a good place to start -- you could begin by sending a simple "hello" to a MATLAB program).
I have done some TCP/IP communication on Linux to poll a temperature sensor and I have done some UDP in Python. Both the Python and C looked very similar, so my limited experience says it is not going to be particularly hard to get messages out to a MATLAB program running as a server. From there you can hack until you get the formatting and timing right.
A Bela AuxiliaryTask example:
https://github.com/BelaPlatform/Bela/blob/master/examples/04-Audio/sample-streamer/render.cpp
In the samplestreamer example data is streamed from disk to the audio output, but easy enough to do something like the reverse where you fill a buffer with audio data in real-time then signal the Aux task to copy a chunk and write it to disk and/or to a server using UDP.
If you are receiving data in MATLAB over UDP could also use MATLAB to write the data to disk on the remote side.
For writing wav files look at examples for doing this with <sndfile.h> directly if you're having trouble with the datalogging functions for Bela.
Here's another example to consider -- a hack way of reading/writing wav without an external library. I am using it on my server to run a guitar effect on a wav file and then outputting the processed audio into a different wav file, triggered by a cgi script. It's terrible hackish code, but it works.
http://cackleberrypines.net/transmogrifox/src/cgi_chorus/csource/
ryjobil Here is one hint for sending real-time data to MATLAB:
https://www.mathworks.com/help/xpc/real-time-udp.html
my understanding is that this is for Simulink only ? Not sure how to integrate it with Matlab. There is otherwise Matlab's dsp.udp
function.
As mentioned elsewhere, there is Udp stuff on Bela that is easy to use:
giuliomoro
- create a C++ Bela project
- #include <UdpClient.h>
- use the UdpClient class, see documentation.You can do this over the USB-network connection, however the gigabit ethernet port on the BeagleBone is most likely going to be more performant if you require a larger bandwidth
There is also an interactive command-line utility in Bela/resources/network
that can be used for testing:
cd Bela/resources/network
gcc udp-client.c -o udp-client
./udp-client localhost 9000
I tried briefly to get it to work with Matlab, and I failed, however, but I blame it on Matlab and not on the udp-client utility, as I also failed when sending from Pd.
giuliomoro Thanks a lot! I will try it. Just to make sure: I can use USB connection to do the UDP transmission, right?
yes you can, however if the required bandwidth is high, then the gigabit ethernet of the BeagleBone Black (assuming that you don't have a BelaMini) is probably the best option
giuliomoro Thanks! I am thinking about connecting Bela to Matlab via usb serial port. Is there any example code in Bela to send data to PC through usb serial port?
leeton I am trying to use the UDP stuff on Bela, but it doesn't work.
You might try this with something like netcat on your remote PC just to see if you can get something to come out of Bela to troubleshoot the basic connectivity issues. This kind of thing can help separate the problems as either
Bela implementation or the MATLAB implementation.
leeton connecting Bela to Matlab via usb serial port
If the amount of data you are sending out of Bela is within USB serial data rates then this is a relatively simple way to this. Assuming what you mean is connecting a USB-to-serial converter to your computer and then connecting the serial to the serial pins on the Bela, then here is some code that communicates with a serial port:
https://github.com/transmogrifox/transmogriFX_bela/blob/master/src/usb_backpack.cpp
https://github.com/transmogrifox/transmogriFX_bela/blob/master/src/usb_backpack.h
Above code reads/writes a USB Serial LCD, but the process is the same setting up any kind of serial port in the Linux environment. I also have some code in which the Bela AuxiliaryTask is used to pass messages from the real-time thread out to the LCD, but it looks like I have not pushed that to github. I can add later if you need it.
Points of interest for basic serial communication are these:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <termios.h>
#include <string.h> // needed for memset
// termios stuff
struct termios tio;
char tty_port[256]; //optional
int tty_fd;
Then setup stuff
display_20x4_lcd* make_20x4_lcd(display_20x4_lcd* d, char* port, bool new_lcd, float fs)
{
// "port" is an ASCII string with the port name, for example "/dev/ttyS0"
d = (display_20x4_lcd*) malloc(sizeof(display_20x4_lcd));
memset(&(d->tio),0,sizeof(struct termios));
d->tio.c_iflag=0;
d->tio.c_oflag=0;
d->tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
d->tio.c_lflag=0;
d->tio.c_cc[VMIN]=1;
d->tio.c_cc[VTIME]=2;
int psz = strlen(port);
for(int i = 0; i < psz; i++)
{
d->tty_port[i] = port[i];
}
d->tty_fd = open(d->tty_port, O_RDWR | O_NONBLOCK);
cfsetospeed(&(d->tio),B115200); // 115200 baud
cfsetispeed(&(d->tio),B115200); // 115200 baud
tcsetattr(d->tty_fd,TCSANOW,&(d->tio));
.
.
.
}
Then to write data out the serial interface:
cmd[] = "some string";
len = strlen(cmd);
// This is a binary write, so you could just as well use an array of integers or floats
// but be careful you get the correct alignment. If low data rates and not a lot information
// text is easy to manage because you don't need to worry about endianness nor byte alignment
write(d->tty_fd, cmd, len); //write 'len' bytes of array cmd[] out to serial port tty_fd
And to read, if you need to
while (read(d->tty_fd,c,100) > 0)
{
// Do stuff with contents in array "c"
}
giuliomoro my understanding is that this is for Simulink only ?
May be true. I haven't done much with MATLAB since university. When something requires IO with the outside world then I use C or Python.
leeton Thanks! I have worked it out by connecting Bela to Matlab via UDP.
can you let us know the details please? It would be good to share that on the other thread as well.
- Edited
giuliomoro Here is my solution. I implement it on Win10. To make it work, we must turn off the firewall first.
I regard the Bela as the client. The code is defined as follows:
#include <Bela.h>
#include <UdpClient.h>
#include <ne10/NE10.h>
#include <sndfile.h>
#include <WriteFile.h>
// separate udp thread with audio thread
AuxiliaryTask gTask;
// udp
UdpClient* audio_client;
const char* remoteIP = "192.168.6.1";
int remotePort = 53448;
float msg[4] = {0.1,0.4,1.2,1.5};
void sendToMatlab(void*);
bool setup(BelaContext *context, void *userData)
{
audio_client = new UdpClient(remotePort,remoteIP);
if((gTask = Bela_createAuxiliaryTask(&sendToMatlab, 96, "send-to-matlab")) == 0)
return false;
return true;
}
void render(BelaContext *context, void *userData)
{
Bela_scheduleAuxiliaryTask(gTask);
}
void sendToMatlab(void*) {
audio_client->send(&msg, 4*sizeof(float));
}
void cleanup(BelaContext *context, void *userData)
{
delete audio_client;
}
And the MATLAB side is implemented as the server. The code is defined as follows:
clc;
clear;
close all;
%% server
localPort = 53448;
u = udp('192.168.6.2','LocalPort',localPort);
disp(u)
u.InputBufferSize = 5000;
u.ByteOrder = 'littleEndian';
fopen(u);
disp('Ready to receive data...')
rece_sw = cell(1);
count = 1;
while 1
data = fread(u,4*4,'float32');
rece_sw{count} = data;
count = count+1;
disp(data)
end
fclose(u);
delete(u);
clear u;
Great thanks