Greetings Teensy users and experts,
I am working on a project where I need to establish communication between a Teensy and a Windows PC.
I am using a USB-HID device with a proprietary API that is available only in the form of a Windows DLL library, so I cannot escape Windows, as per my understanding.
After receiving data from the device, I perform some calculations, and then send commands to a Teensy 4.0, which drives some LED's and motors.
The bottleneck in my process is the Windows->Teensy communication. I do not need the Teensy to talk back to the PC, but I need the Teensy to listen to the PC.
Currently, I am using the easiest way to do that i.e. USB Serial. In one of the older posts on the Arduino forums, @Paul posted some test results showing that the Serial latency between Teensy/PC is <4ms for data packets < 12bytes (https://forum.arduino.cc/t/reduce-serial-latency/59748/10) . However, no matter the size of my packets, I am getting a steady delay of ~15ms per send command. I've read in multiple posts that it might be scheduling latency from the OS. I've also tried setting the thread priority higher to no avail.
I'm sure that I'm approaching this incorrectly. I'm looking for some guidance regarding whether this is even the right way to go about "talking" to a Teensy at a latency <4ms. If yes, how may I achieve that threshold? If no, what are some alternatives I could use?
I appreciate your kindness in advance.
I am attaching barebone scripts that I used to characterize how long it takes for the PC to send a message over Serial to the Teensy, which does not change whether or not the rest of my code is included with it. Using these scripts, I get a latency of ~15ms per send command.
You will notice a sleep delay in the Windows side script. If I set that delay to anything under 1ms or remove it altogether, then the apparent latency is <0.0ms, which I think might be an error. However, any value including and over 1000us or 1ms to anything under 10ms will always generate 15ms delay. Say, I set the delay to 100ms, then the time per loop will be ~115ms.
I am working on a project where I need to establish communication between a Teensy and a Windows PC.
I am using a USB-HID device with a proprietary API that is available only in the form of a Windows DLL library, so I cannot escape Windows, as per my understanding.
After receiving data from the device, I perform some calculations, and then send commands to a Teensy 4.0, which drives some LED's and motors.
The bottleneck in my process is the Windows->Teensy communication. I do not need the Teensy to talk back to the PC, but I need the Teensy to listen to the PC.
Currently, I am using the easiest way to do that i.e. USB Serial. In one of the older posts on the Arduino forums, @Paul posted some test results showing that the Serial latency between Teensy/PC is <4ms for data packets < 12bytes (https://forum.arduino.cc/t/reduce-serial-latency/59748/10) . However, no matter the size of my packets, I am getting a steady delay of ~15ms per send command. I've read in multiple posts that it might be scheduling latency from the OS. I've also tried setting the thread priority higher to no avail.
I'm sure that I'm approaching this incorrectly. I'm looking for some guidance regarding whether this is even the right way to go about "talking" to a Teensy at a latency <4ms. If yes, how may I achieve that threshold? If no, what are some alternatives I could use?
I appreciate your kindness in advance.
I am attaching barebone scripts that I used to characterize how long it takes for the PC to send a message over Serial to the Teensy, which does not change whether or not the rest of my code is included with it. Using these scripts, I get a latency of ~15ms per send command.
You will notice a sleep delay in the Windows side script. If I set that delay to anything under 1ms or remove it altogether, then the apparent latency is <0.0ms, which I think might be an error. However, any value including and over 1000us or 1ms to anything under 10ms will always generate 15ms delay. Say, I set the delay to 100ms, then the time per loop will be ~115ms.
C++:
//
// Script for testing simple Serial read on the Teensy side
//
#include <Arduino.h>
void setup(){
Serial.begin(115200);
}
void loop(){
if (Serial.available()){
byte c = Serial.read();
}
}
C++:
//
// Script for testing simple Serial write on the Windows side.
// Disclaimer: Includes AI-generated code
//
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <chrono>
#include<cstdlib>
#include<csignal>
#include<thread>
using namespace std;
//---signal handler for ctrl_C
volatile sig_atomic_t ctrlCPressed = 0;
// Signal handler function
void signalHandler(int signal) {
if (signal == SIGINT) {
printf("Ctrl+C pressed. Stopping program.\n");
ctrlCPressed = 1;
}
}
//---Serial functions
#define TEENSY_PORT "COM9"
HANDLE openSerialPort(const char *portName, DWORD baudRate);
bool sendMessageToTeensy(HANDLE serialPort, const char *message);
//--Serial variables
const int bufferSize = 6;
char buffer[bufferSize];
int main() {
//set up time variables
auto lastTime = chrono::high_resolution_clock::now();
auto timeDiff = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - lastTime);
//set up serial
const char *portName = TEENSY_PORT;
char message = 'y';
HANDLE teensySerial = openSerialPort(portName, CBR_115200);
printf("Simple serial test");
while(!ctrlCPressed){
timeDiff = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - lastTime);
printf("dT: %lld ms \n", timeDiff.count());
lastTime = chrono::high_resolution_clock::now();
sendMessageToTeensy(teensySerial, &message);
this_thread::sleep_for(10ms); //change this value to see if it makes a difference
}
printf("ctrl_c pressed");
return 0;
//end main
}
HANDLE openSerialPort(const char *portName, DWORD baudRate) {
HANDLE serialPort = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (serialPort == INVALID_HANDLE_VALUE) {
printf("Error opening serial port.\n");
return nullptr;
}
DCB serialParams = {0};
if (!GetCommState(serialPort, &serialParams)) {
printf("Error getting serial port state.\n");
CloseHandle(serialPort);
return nullptr;
}
serialParams.DCBlength = sizeof(DCB);
serialParams.BaudRate = baudRate;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
if (!SetCommState(serialPort, &serialParams)) {
printf("Error setting serial port state.\n");
CloseHandle(serialPort);
return nullptr;
}
printf("Connected to %s",portName);
return serialPort;
}
bool sendMessageToTeensy(HANDLE serialPort, const char *message) {
DWORD bytesWritten;
if (!WriteFile(serialPort, message, strlen(message), &bytesWritten, nullptr)) {
printf("Error writing to serial port.\n");
return false;
}
else{
FlushFileBuffers(serialPort);
}
return true;
}