I know this is an old post, but I will still post a reply here in case of any future readings.
I am trying to sample single-channel data (16 bit) at high (>=1000 Hz) and reliable sampling rate via Matlab from an Arduino Leonardo. Sounds impossible but now I believe I have achieved it. But please let me know if I have made any mistakes.
Environment: Matlab R2017b Update 7, Windows 10 1803, Arduino Leonardo.
There are several key-points here. First, both Matlab’s Arduino support packages and built-in serial object are very slow. I have to use 3-rd party mex sampling tools. I use this one (Mex_C_Serial_Interface - File Exchange - MATLAB Central). After downloading it, modify “CSERIAL_FLOW_NONE” at line 33 of “openPort.c” to “CSERIAL_FLOW_HARDWARE”, so that Arduino can automatically transfer new data once the input buffer is being read. I compiled the mex files in Matlab using Visual Studio Ultimate 2013 without any errors.
Second, don’t set the sampling rate in Matlab code, set it in the Arduino code, and transfer the timestamp associated with each data point together. Arduino has a delayMicroseconds() function that is very precise so your sampling rate won’t have any large jitters. You can get timestamp with Arduino’s “micros()” function.
Third, at high sampling rate, you need higher baudrate and more compact data transfer. I specify baudrate=115200, and transfer data every 1 ms using Serial.write(). Here the timestamp returned by “micros()” is unsigned long (32-bits, 4 bytes), and sensor value returned by analogRead() is int (16-bits, 2 bytes), so for each sample I make a 6-elements byte array to store timestamp and sensor data together and send this byte array with Serial.write(). On the Matlab side, read serial port as fast as you can (reading interval should be smaller than Arduino’s data sending interval), so the FIFO buffer won’t filled-up (That’s why I need a high-speed serial port reader instead of MATLAB’s built-in slower one). The mex tool I mentioned can only read data in array of bytes, so I use Matlab’s “typecast()” function to combine the first 4 bytes to form the timestamp value, and combine the last 2 bytes to form the sensor data.
To validate this method, I sample my computer’s screen brightness (1000 Hz sampling rate) with an analog photo-resister attached to Arduino Leonardo. I flash the screen black-then-white with PsychToolbox’s “PerceptualVBLSyncTest” function at highest refresh rate (60 Hz) while sampling. Attached is the result. The upper part is the screen-brightness data. There are 30 cycles in a second, and in each cycle the screen refreshed twice (white-black-white), so the refreshrate is 60 Hz. The lower part is the sample interval calculated by the difference between consecutive timestamp data. The sample interval is around 0.001 s, and the jitter is about 7%. This is much better than matlab’s built-in serial object.