Communication Quattrocento/MATLAB with timer function
Quote from mikael.desmons on 4 March 2024, 9:19Hi,
I'm trying to acquire and plot in real time the EMG from the Quattrocento in MATLAB . The code is based on the example present on the website of OT. In order to have more control on the plot and to make it faster, I use a timer function (at a defined speed, for example a call every 0,2s) to read what is coming from the TCP socket. When we read (function read of fread) the signal, I try to read all the bytes that are available:
NumBytesAvailable= parameters.tcpSocket.NumBytesAvailable;DataQuattrocento = read(parameters.tcpSocket, NumBytesAvailable , 'int16')';DataQuattrocento = reshape((DataQuattrocento),120,[]);Sometimes the number of bytes is odd, and some bytes are missing to complete the matrix of the 120 channels. Is there a reason why the number could be odd ?
Thank you in advance for you help
Hi,
I'm trying to acquire and plot in real time the EMG from the Quattrocento in MATLAB . The code is based on the example present on the website of OT. In order to have more control on the plot and to make it faster, I use a timer function (at a defined speed, for example a call every 0,2s) to read what is coming from the TCP socket. When we read (function read of fread) the signal, I try to read all the bytes that are available:
Sometimes the number of bytes is odd, and some bytes are missing to complete the matrix of the 120 channels. Is there a reason why the number could be odd ?
Thank you in advance for you help
Quote from Simone on 4 March 2024, 10:02Dear Mikael,
I'd expect that the data coming from the device is always a multiple of packet size but I think something can happen at Ethernet-cable level and data can be buffered somewhere in the middle.
My suggestion is: instead of reading all data available read multiple of packet size (or packet size itself). I think that if you wait for more data than available the read function wait until the specified amount is ready.
On the other hand you can bufferize the data and handle the correct size on yourself but it would be a bit more complex to do.
Dear Mikael,
I'd expect that the data coming from the device is always a multiple of packet size but I think something can happen at Ethernet-cable level and data can be buffered somewhere in the middle.
My suggestion is: instead of reading all data available read multiple of packet size (or packet size itself). I think that if you wait for more data than available the read function wait until the specified amount is ready.
On the other hand you can bufferize the data and handle the correct size on yourself but it would be a bit more complex to do.
Quote from Enrico on 4 March 2024, 11:40Some more details:
The quattrocento send data over TCP on blocks with fixed size, as soon as the PC is ready to receive them.
The blocks contains the data of few samples. The size of the blocks and the number of samples included in a block depends on the number of active channels (NCH<1:0> bits in the ACQ_SETT BYTE, see the configuration protocol).
In particular:
NCH<1:0> = 00 means IN1, IN2 and MULTIPLE IN 1 are active. Data is grouped and sent every 12 samples and the block size is 12samples*120channels*2bytes = 2880 bytes
NCH<1:0> = 01 means IN1 to IN4, MULTIPLE IN 1 and MULTIPLE IN 2 are active. Data is grouped and sent every 6 samples and the block size is 6samples*216channels*2bytes = 2592 bytes
NCH<1:0> = 01 means IN1 to IN6 and MULTIPLE IN 1 to MULTIPLE IN 3 are active. Data is grouped and sent every 4 samples and the block size is 4samples*312channels*2bytes = 2496 bytes
NCH<1:0> = 01 means all the inputs are active. Data is grouped and sent every 2 samples and the block size is 2samples*408channels*2bytes = 1632 bytesThe number of channels includes the EMG channels, the AUX channels and the accessory channels (see again the configuration protocol for details).
Reading too quickly is not efficient, especially in Matlab. Consider to read data every 50 or 100 ms.If data is not read by the ethernet card of the PC, it is accumulated inside the output buffer of quattrocento. It can hold up to 20480 samples.
One of the auxiliary channels reports the number of sample that can still be stored in the output buffer.
Some more details:
The quattrocento send data over TCP on blocks with fixed size, as soon as the PC is ready to receive them.
The blocks contains the data of few samples. The size of the blocks and the number of samples included in a block depends on the number of active channels (NCH<1:0> bits in the ACQ_SETT BYTE, see the configuration protocol).
In particular:
NCH<1:0> = 00 means IN1, IN2 and MULTIPLE IN 1 are active. Data is grouped and sent every 12 samples and the block size is 12samples*120channels*2bytes = 2880 bytes
NCH<1:0> = 01 means IN1 to IN4, MULTIPLE IN 1 and MULTIPLE IN 2 are active. Data is grouped and sent every 6 samples and the block size is 6samples*216channels*2bytes = 2592 bytes
NCH<1:0> = 01 means IN1 to IN6 and MULTIPLE IN 1 to MULTIPLE IN 3 are active. Data is grouped and sent every 4 samples and the block size is 4samples*312channels*2bytes = 2496 bytes
NCH<1:0> = 01 means all the inputs are active. Data is grouped and sent every 2 samples and the block size is 2samples*408channels*2bytes = 1632 bytes
The number of channels includes the EMG channels, the AUX channels and the accessory channels (see again the configuration protocol for details).
Reading too quickly is not efficient, especially in Matlab. Consider to read data every 50 or 100 ms.
If data is not read by the ethernet card of the PC, it is accumulated inside the output buffer of quattrocento. It can hold up to 20480 samples.
One of the auxiliary channels reports the number of sample that can still be stored in the output buffer.
Quote from mikael.desmons on 4 March 2024, 12:57Dear Simone and Enrico,
Thank you for your responses.If I read a fixed amount of bytes, I expect to experience some delays in my almost real-time plot. I have observed that occasionally, 0 bytes are available, and then the read function reads all bytes, including those that were delayed, in order to catch up on the delay. When using a fixed amount of bytes, I expect that whenever there is nothing to read, it will simply postpone the new bytes and read the ones I missed a few iterations before.
I was considering implementing a buffer to handle the correct size, as you suggested, Simone. However, after reading Enrico's response, I understand that the number of samples sent is dependent on the number of channels, which makes sense but also adds a level of complexity to my buffer.
My goal is to read the data every 100 or 200 ms. What I don't understand is: if the data are stored in the buffer of the Quattrocento waiting for the computer to be able to read, it should send a full package corresponding to the matrix (e.g., 120 channels), but I am receiving these odd numbers of bytes. Is it possible that my timer function, which calls the read function every 200 ms, sometimes requests a package that is not full? Have you encountered this issue while developing software for the Quattrocento?
Dear Simone and Enrico,
Thank you for your responses.
If I read a fixed amount of bytes, I expect to experience some delays in my almost real-time plot. I have observed that occasionally, 0 bytes are available, and then the read function reads all bytes, including those that were delayed, in order to catch up on the delay. When using a fixed amount of bytes, I expect that whenever there is nothing to read, it will simply postpone the new bytes and read the ones I missed a few iterations before.
I was considering implementing a buffer to handle the correct size, as you suggested, Simone. However, after reading Enrico's response, I understand that the number of samples sent is dependent on the number of channels, which makes sense but also adds a level of complexity to my buffer.
My goal is to read the data every 100 or 200 ms. What I don't understand is: if the data are stored in the buffer of the Quattrocento waiting for the computer to be able to read, it should send a full package corresponding to the matrix (e.g., 120 channels), but I am receiving these odd numbers of bytes. Is it possible that my timer function, which calls the read function every 200 ms, sometimes requests a package that is not full? Have you encountered this issue while developing software for the Quattrocento?
Quote from Enrico on 6 March 2024, 9:44Hi Mikael,
consider that you are not communicating directly from Matlab with the quattrocento. Between your script and the ethernet port there are several other layers that are under the control of the Operative System, the ethernet card drivers or hardware and also the firewall or antivirus. Moreover, if you use a ethernet/USB adapter, there is also the USB driver and port. All these layers have additional buffering system with FIFOs.
In our software we don't read data at timered intervals but we wait to get a defined amount of bytes. If you really need a more regular reading, you can try to check the settings of the intermediate layers/drivers. If you really need a close real time system consider to use a different OS (I am supposing you are using Windows or IOS).
Hi Mikael,
consider that you are not communicating directly from Matlab with the quattrocento. Between your script and the ethernet port there are several other layers that are under the control of the Operative System, the ethernet card drivers or hardware and also the firewall or antivirus. Moreover, if you use a ethernet/USB adapter, there is also the USB driver and port. All these layers have additional buffering system with FIFOs.
In our software we don't read data at timered intervals but we wait to get a defined amount of bytes. If you really need a more regular reading, you can try to check the settings of the intermediate layers/drivers. If you really need a close real time system consider to use a different OS (I am supposing you are using Windows or IOS).
Quote from mikael.desmons on 11 March 2024, 9:39Hi Enrico,
Thank you for your help and your answers. I'll keep working on this.
Hi Enrico,
Thank you for your help and your answers. I'll keep working on this.