Continuously write and read from serialport
28 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Is there a method to send data to the USB serial port in a continuous manner? I would like the data to be "send again" once the receive buffer has received almost all bytes there were sent.
I saw older posts that address a similar issue. The 224393 post suggests a link that is not working, and sends the user to the instrument toolbox. The 143515 post uses the old serial function, and not the serialport recommended.
I am using Matlab to send data to a Teensy connected on the USB serial port COM19.
Teensy runs a timer that reads the USB serial port, then writes back (loop-back) the values received. If the timer interrupts, and no data was received, Teensy sends back the previously read data.Missed data looks like a short horizontal line when I plot the received data in Matlab.
I found that the fastest period I can achieve is slightly less than 1kHz, even though I send the data as packets of 4096.
Matlab uses an USB buffer of 4096, while Teensy uses a buffer of 8192 bytes. I would like to send 4096 bytes, and re-send the bytes immediately after I received {N*4096 + 2048} where N is a natural number and 2048 is a guess that would insure I do not overflow the 8192bytes buffer on Teensy.
Is there a fast way to check number of bytes received on the USB port so we can send new data before is needed?
I can run the teensy code with a 1KHz repetition rate, but I could run it at 100KHz if I accept small gaps in the data received.
I would like to run it at a higher rate than 1kHz without the gaps in data received.
below is a plot of data received that shows a small gap at 8192 data received. Follwing is a picture that uses a sampling of 50KHZ and has more and bigger gaps. I was running matlab with runtime prority high.


MAtlab code below:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
%%%%%%USER SETUP
USBPORT = 'COM19'; %UPDATE w/ Teensy COM port
delete(instrfindall); %Delete any hung COM ports
USB = serialport(USBPORT,6000000);
% serialport runs through USB, with a speed of 480MBit/s, but it has a
% buffer of 4096 bytes. No data is send until buffer is filled.
% Matlab does not use push commands to send data immediately
USB_Buffer_Size= 4096;
DAC = [];
for i = 0 : USB_Buffer_Size-1
DAC = [DAC, uint16(2048*sin(i*8*pi/USB_Buffer_Size)+2048)]; % 4096 corresponds to 2*pi
end
plot(DAC);
x=[];
nowriteflag = 0; % flag to know when not to write new USB buffer
y=0;z=0;
tic
flush(USB);
write(USB,DAC,"uint16");
while (toc<60)
if (USB.NumBytesAvailable>15)
y = y + USB.NumBytesAvailable;
x =[x,read(USB,USB.NumBytesAvailable,"uint16")];
if (y > z + USB_Buffer_Size/4)
if(nowriteflag == 0)
nowriteflag = 1;
write(USB,DAC,"uint16"); %write new buffer if 1/4 buffer received
end
end
if (y > z + 4096)
z = z + USB_Buffer_Size;
nowriteflag = 0;
end
end
end
plot(x);
Teensy code below:
#include <SPI.h> // include the SPI library:
const int slaveSelectPin = 10;
const int Sample_uS = 1000; // period in microseconds
SPISettings SPISettingsDAC = SPISettings(20000000, MSBFIRST, SPI_MODE1);
IntervalTimer usbRX; // declares interval timer to impose a known period on USB received data
uint8_t LSByte, USByte = 0;
////////////////**********///////////
void setup() {
pinMode (slaveSelectPin, OUTPUT); // set the slaveSelectPin as an output:
SPI.begin(); // initialize SPI:
SPI.beginTransaction(SPISettingsDAC);
//******** Interval Timer to call repeately to send data to the DAC
usbRX.priority(1); // just reset is higher
usbRX.begin(usbRXTXdacTX, Sample_uS); // usbRXdacTxfunction runs every Sample_uS
}// void setup() end
void loop() {
// everithing is done timed by an interval timer set in the void setup()
}// loop
void usbRXTXdacTX()
{// this function reads 2 bytes from the USB serial and sends them to the DAC. Simple, no processing
if (Serial.available() > 0) // check for serial received, and capture data
{
LSByte = Serial.read();
USByte = Serial.read();
digitalWrite(slaveSelectPin,LOW);
uint16_t DACbits = (USByte << 8) | LSByte;
SPI.transfer16(DACbits);
digitalWrite(slaveSelectPin,HIGH);
}// end if (Serial.available() > 0)
Serial.write(LSByte); // Send the lower byte
Serial.write(USByte); // Send the upper byte
}// end usbRXTXdacTX
2 Kommentare
chrisw23
am 21 Jun. 2023
Change to async communication by using callbacks. Define a usable byte length for event thresholds on both sides.
Timothy Maxwell
am 21 Feb. 2024
Bearbeitet: Timothy Maxwell
am 21 Feb. 2024
Replying only to follow along months later. Was searching for how to do a continuous serial stream without the intermediate serial buffer, and for almost the same reason!
I have an RP2040 reading an accelerometer and streaming back 8-byte packets at over 3k packets/second (!?).
Amazed to see it working, but I also just realized there are some kind of gaps in the data once every 0.7 seconds or so and also suspect the serial buffer pauses. The result is an unphysical frequency comb when I analyze spectra from the sensor.
Will keep searching, unless you ever figured this out?
Antworten (0)
Siehe auch
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!