how to usb device serial output connect to teensy 4.0 usb

Thanks all the problem solved.

I lost like a week for that 0x00 and feeling like :eek::(:confused::p

I still do not know where that 0x00 is coming, but USB_serial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER)-1); solved the problem (at least this problem)

The strange thing and what made this difficult to find out is that Loupe deck responds as it should despite the additional 0x00, but for semi reason it remains on buffer and messes up the next message, though one would imagine it would look for the 0x82 to start next message reception....

Note there is also the

"BTW, this trickers "*** Empty ***"

for (uint16_t i = 0; i < 512; i++) {USB_serial.write((uint8_t)0x00); }

Why is that if it should be able to handle 512 bytes?"

I mentioned earlier, is there some buffer size problem when using USBSerial_BigBuffer etc.?
 
Last edited:
...

Why is that if it should be able to handle 512 bytes?"

I mentioned earlier, is there some buffer size problem when using USBSerial_BigBuffer etc.?

What happens with the 512 byte message? All the flow is examined/exposed correct? Is there an odd packet and a second packet or no packet at all?

@KurtE was doing MTP file transfer and there was something ODD about 512 byte file transfers - and recurred on every multiple of 512B as well.

It required some change/edit/workaround in the code to work with the test file set I created that made files of all sizes where they would ALL work - except those on the 512B boundaries. That was using Windows - not sure if it affected linux.

The end result was those files were corrupted after transfer where all other files were verifiably correct. ALL went working after @KurtE saw and fixed the issue in the MTP transfer code that uses USB to present the Teensy as an MTP data drive.
 
How does this affect writing a lot of data, like 194400 bytes, how should I do that?

for (uint32_t i = 0; i < 199400; i++) {USB_serial.write(DATA);} or?

Now figuring couple of other things first, but will soon try that.
 
For the most part it does not matter, in this case.

That is you could also do: USB_serial.write(DATA, 199400);
But then again, the USBSerial class does not overwrite this, and as such uses the default
implementation out of the Print class:

Which does:
Code:
size_t Print::write(const uint8_t *buffer, size_t size)
{
	if (buffer == nullptr) return 0;
	size_t count = 0;
	while (size--) count += write(*buffer++);
	return count;
}

Maybe at some point may overwrite that case, and do a little quicker copy of data from your buffer to the internal
buffers, but comparing the speed of the copy of the data versus the time for the USB transfer times, not sure if you
will notice much of a difference.
 
I am now testing the screen update. Everything basically works, but stability issues. On this video updating one button area with noise to test update rate

https://youtube.com/shorts/qKIs7USWq5c?feature=share

Sometimes it runs for a minute, often shorter.

Once again, it could be my code, the device or the USB Host. The device is not really designed for this kind of use, but would be nice if it tolerates it, so could be the device.


The original problem I had was that when sending

char WS_UPGRADE_HEADER[] = "GET /index.htm\r\nHTTP/1.1\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";

USB_serial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER));

It adds a zero at the end. why is that

the solution I am now using is this USB_serial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER)-1); and that works.

also what I noted above

"BTW, this trickers "*** Empty ***"

for (uint16_t i = 0; i < 512; i++) {USB_serial.write((uint8_t)0x00); }

Why is that if it should be able to handle 512 bytes?"

is this as it is supposed to be?

So suspecting a bit that it could be also the USB Host when sending big amount of data, receptively and fast. That it sends or misses few bytes. The devise is very demanding the data being exactly right.
 
so is it writing 0-at-the-end because the data was of type char??

Is there other weird USB_serial.write() I should know of than writing 0-at-the-end in case of type char and not accepting write 0, but requires defining USB_serial.write((uint8_t)0x00);

The display allows defining update area, a small area like 15x15 pixels seems to be ok, the size of that is 15*15*2 = 450 bytes so fits one 512 buffer, maybe the reason it does not seem to fail like bigger writes. But also the bigger writes might be ok for 100 times, but then randomly fail (or something else randomly fails)

I am waiting confirmation from Loupedeck after each image write that the previous one was ok before sending new one. The Loupedeck is very sensitive for wrongly formatted messages, one wrong or missing byte and it hangs or goes to sleep, and this is what is happening randomly when updating bigger images fastest possible rate.(the bigger images do randomly fail also at slower rates, that is a real problem)

I would like to update one button area at the time 90x90 pixels 16 bit colour + header, about 16230 bytes per image. The faster the better, I think the display can do about 30 fps maybe more, so that is 0.5 Mbytes per second...

Should make the image update on LabView code to test if it fails also on that...

But asking if there is some known issues with Teensy 4.1 USB Host that could cause this?
 
Last edited:
so is it writing 0-at-the-end because the data was of type char??
The code:
Code:
char WS_UPGRADE_HEADER[] = "GET /index.htm\r\nHTTP/1.1\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
creates a Zero terminated string. ie the last character is 0x00.
USB_serial.write() is sending every component of that string.
 
I do not understand what that means, so is this 0-at-the-end because the data was of type char, I do not see that with uint8_t (maybe should verify? but did not notice)

just a side note, why would it be in any way wanted operation that write adds anything that I did not tell it to send over serial?

Note: it seems also sizeof sees that additional 0 as this removed it. USB_serial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER)-1); I am no longer using sizeof() as I do not understand it, just hard code, but need to use write.
 
You could try:
Code:
        USB_serial.print(WS_UPGRADE_HEADER);
.print expects a string and recognises the 0x00 as a terminating byte(char).

just a side note, why would it be in any way wanted operation that write adds anything that I did not tell it to send over serial?
It does exactly what you told it to. You (the compiler) created a zero terminated string and you asked it to send that string over USB_serial.

Take a look at this, it might better explain what is happening for you.
 
So how should WS_UPGRADE_HEADER[] = "GET /index.htm\r\nHTTP/1.1\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"; be defined so that it is exactly and only what is defined, to send over serial exactly that.
 
So how should WS_UPGRADE_HEADER[] = "GET /index.htm\r\nHTTP/1.1\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"; be defined so that it is exactly and only what is defined, to send over serial exactly that.

See my post #86 which crossed with your comment.

If you want to use serial.write then define WS_UPGRADE_HEADER[] as an array of byte:
Code:
uint8_t      WS_UPGRADE_HEADER[] = "GET /index.html\r\n"
"HTTP/1.1\r\n"
"Connection: Upgrade\r\n"
"Upgrade: websocket\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";

// and use 

        Serial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER));
Because WS_UPGRADE_HEADER is NOT defined as an array of char it does NOT have the zero terminating byte.

I have not tried any of the above as I do not have the required equipment but I can confirm that they compile ok.
 
Oh well that just took 60 hours of my life, to find the problem it caused, will but char to my use only for printing, otherwise convert the hex and define uint8_t. anyway that problem is now solved. the remaining question is, is there known issues related to Teensy 4.1 USB Host that could cause the big writes randomly fail, if not I need to build complicated and not that good workaround it seems.
 
What kind of constant data rates are reasonable to expect form Teensy 4.1 via USB Host serial?

The Loupedeck is now somewhat working, testing on this with random generated pixels, drawing each display area separately.

https://vimeo.com/773350727/06cf1e8f69

This would be great if it would be reliable, now there is still some issues with that. Normally we will be updating only one button area at at the time, that is fast.

The data rate, I tested updating the centre display only, drawing the complete are at once. That works only for few seconds but provides about 10 fps 360x270 pixels 16 bit colour, so almost 2 Mbytes per second. Is this starting to be the limit for Teensy 4.1 USB Host serial? It could be also the Loupedeck limit.
 
Sorry, I have no idea in this case on what the limits will be for your device.

Once things are setup, the code simply sends the buffers to the other side...

There are lots of things that can influence the throughput.

For example: I am guessing that your device is running at: USB Full Speed - 12Mega Bits per second. So probably top end is then 12/8. Or about 1.5Mega Bytes per second.
I would assume that that would be if every USB frame was used and the 64 byte packets were filled. Now if it ran at High Speed, like a few USB Serial adapter do, this would be 480M Bits per second.
And each packet could be up to 512 bytes.

Looking at the RAWHID page: https://www.pjrc.com/teensy/rawhid.html - you will notice that it says you can send up to 1000 packets per second each direction.. And again this is 64 byte packets.
I have a version of RAWHID that I setup to run at high speed and if I remember correctly, it did show about 15 times throughput.

Also if you do things like, SerialUSB.flush() much at all, and on average each packet is only half full, you reduced your throughput more or less in half.

And with USB, it may also depend on if other devices are also connected doing things.

It will also depend on how fast your actual device grab data. For example, if the device is some form of USB to Serial adapter, that talks to another internal chip through an UART, then how fast is this UART running.
 
The device interface is high speed, but that of course does not tell about how fast rates it can handle.

My question, what kind of speeds could be expected from Teensy 4.1 USB Host serial under ideal conditions.

1000 packets of 64 bytes would be just 64 kbytes/second. 15 that would still be less than 1 M byte /s

I did not make any detailed measurements, but think the max I am seeing is closer to 2 M bytes/s but the question, could it be the teensy that is limiting that?
 
We have nothing in there that is deliberately trying to slow it down.

And I am assuming you are using the USBSerial_BigBuffer class to handle it. That is if it is marked as High Speed,
it will have the RX/TX on the endpoints marked as 512 bytes.
 
As far as I know, nobody has done much benchmarking on USB host serial driver speed, so the only info available would be guesswork.

My guess is software overhead inside USBHost_t36 probably limits the speed to the 6 to 12 MByte/sec range, if the sketch code reading/writing data and the USB device connected to Teensy 4.1's host port aren't the speed limiting factors.

But the only reason I would guess this range is we were seeing about 200-350 kline/sec on the device side in the lines/sec benchmark, where each line is about 33 bytes, in the early days of Teensy 4.0 before a lot of work went into optimizing the code (and optimizing Arduino's Serial Monitor so the entire Arduino IDE wouldn't lock up or crash). This experience with benchmarking device mode may or may not be relevant to host mode.

Regarding the USB protocol, at high speed the packets should be 512 bytes, if the USB device transmits efficiently. But many of them do not. While probably not a factor with bulk protocol, at high speed the USB bandwidth is managed in microframes which are 125 us (8000 per second). Each microframe can fit several 512 byte packets. But if only 1 max size packet were sent in each microframe, you'd see 4 Mbyte/sec speed.
 
Back
Top