Rpi Pico Usb device mode

Eduard2

Golden Member

Beste forumleden,

Heeft iemand de USB mogelijkheden van de Rpi Pico al verkend ?

Vanuit een pico C programma "Hello world" over USB naar de pc sturen lukt. Met een tellertje heb ik intussen uitgevlooid dat zoiets aan ongeveer 10 kbs werkt. Ik wil sneller info van pc naar de pico sturen. De pico ondersteunt TinyUsb device mode. Heeft iemand dat al uitgetest ?

Vriendelijke groeten,

Eduard

Shiptronic

Overleden

Wat is "TinyUsb device mode" ??

Wie de vraag stelt, zal met het antwoord moeten leren leven.
Arco

Special Member

Als het een HID slave is, dan is de throughput 8kByte in low speed mode, en 64kByte in hi speed mode (max)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Volgens mij toen ik dat probeerde was ie gewoon een USB-CDC.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Eduard2

Golden Member

Beste forumleden,

Iedereen alvast bedankt voor het meedenken.

@Arco: Het forum heeft al direct iets opgeleverd. Je drukt me met de neus op een telfout. Het goede nieuws is dat de snelheid hoger ligt dan ik eerst schreef. Als proef werd in C taal een lus geprogrammeerd. Die lus doorloopt de getallen tussen honderduizend en 1 miljoen.Met printf("%d /n",i) worden die via usb op het pc scherm geprint. Dat geeft 900000 getallen van 6 cijfers. Samen met de CR LF bij het einde ieder getal komt dat neer op 900000 * 8 bytes in 80 seconden. Die tijd werd vastgesteld met een polshorloge dus er zal wat marge op zitten. Als ik geen redeneerfout maak zijn dat negentigduizend bytes per seconde. Dat is een pak beter dan ik eerst becijferde maar het blijft te laag. USB moet sneller kunnen.

@Shiptronic: TinyUsb is een open software die op microcontrollers kan worden geïnstalleerd. Het laat toe de usb te gebruiken in Device of Host mode. Sluit je een pico die met TinyUsb is geprogrameerd aan op een pc dan beschouwt de pc de pico als een ding waarin hij kan lezen en schrijven. In die situatie is de pc de baas. Dat is wellicht de device mode. Er bestaat ook Host mode. In dat geval kan de pico zelf usb gebruiken om bv een memorystick te lezen. Neem me niet kwalijk als er fouten in deze uitleg zouden staan. Het is mijn interpretatie van info op verschillende sites. Surf maar eens naar www.tinyusb.org.

@rew: Heb je al iets met USB geprogrammeerd op de pico ? De voorbeelden in de SDK map zijn voor mij best moeilijk. Ik ben geen professionele programmeur. Eerste knelpunt is het uitvlooien van de opstelling waarin die dingen getest kunnen worden. Neem het voorbeeld van de headphone. Nergens vind ik hoe de muziek naar de usb moet worden gestuurd op de pc. Aan de kant van de pico is het me nog niet duidelijk hoe en waar het audiosignaal kan worden afgetakt.

Vriendelijke groeten,

Eduard

Arco

Special Member

Met full speed USB en bulk transfers kun je max. 12Mbit/sec halen.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

USB 1.1. Dus inderdaad 12 Megabit per seconde bruto snelheid. Een flink deel daarvan heeft hij nodig voor USB protocol overhead. Dus de netto effectieve snelheid zit daar nog een flink stuk onder.

Hensz

Golden Member

Op 7 juni 2021 20:00:06 schreef Eduard2:...Met printf("%d /n",i) worden die via usb op het pc scherm geprint. Dat geeft 900000 getallen van 6 cijfers. Samen met de CR LF bij het einde ieder getal komt dat neer op 900000 * 8 bytes in 80 seconden. Die tijd werd vastgesteld met een polshorloge dus er zal wat marge op zitten.

Er zal veel meer marge ontstaan door het formatteren van de getallen, de prinf-code en 900000 handshakes tussen je pico en de host/slave, nog afgezien van het feit dat het OS er ook nog wel hier en daar z'n neus tussen zal steken.
Je hebt goede kans dat het al sneller is als je een string (van random chars) maakt en die tig keer verstuurt.

Don't Panic!

Op 7 juni 2021 22:18:08 schreef Arco:
Met full speed USB en bulk transfers kun je max. 12Mbit/sec halen.

Met overhead en zo... moet je blij zijn met 1 Mbyte /sec. Dat is 8 Mbit/sec effectief.

Neem het voorbeeld van de headphone. Nergens vind ik hoe de muziek naar de usb moet worden gestuurd op de pc. Aan de kant van de pico is het me nog niet duidelijk hoe en waar het audiosignaal kan worden afgetakt.

Wat ik verwacht is dat de pico dan op USB-niveau roept: "Hoi, ik ben een USB-audio device". Ieder audio-systeem op de PC moet dan de audio daarheen kunnen sturen.

Het signaal aftakken: ik zou denken dat er 1 of 2 pins zijn die "DAC" er bij hebben staan. Daar staat dan het signaal op. Dat kan je beschouwen als "headphone outputs". Een condensator en een koptelefoon-luidspreker is voldoende om dat te beluisteren.

Als test zou ik blokken van bijvoorbeeld 1k versturen:

code:


void test_usb_speed (int nmbyte)
{
  int i;
  static char buf[1028];

  for (i=0;i<1024;i++) {
    buf[i] = 'A' + (i % 26);
  }

  for (i=79;i<1024;i+=80) {
    buf[i] = \n;
  }
  buf[1023] = '\n';
  buf[1024] = '\0';

  for (i=0;i<nmbyte;i++) {
     sprintf (buf, "%d.....", i);
     // write (???, buf, 1024);
     printf ("%s", buf);
  }
}

Ik zou zoiets maken om de boel te testen. 1 kb print tegelijk, groot deel prepared data, identificatie van het datablok.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Eduard2

Golden Member

Goede morgen,

Het forum heeft zijn doel bereikt. Met deze informatie kan ik weer aan de slag. Het zit er dik in dat de snelheid hoog genoeg is om een 16bit audiosignaal met 44,1 kHz samplerate over de usb te sturen.

Als volgende proef ga ik de rollen omdraaien. De pc gaat data op de usb sturen en de pico zal die op aansluitpinnen brengen. Met de oscilloscoop kan dan worden bekeken welke snelheid haalbaar is.

Ik verwacht dat Hensz gelijk heeft. Daarom begin ik nu met grotere rijen getallen. Als de snelheid nog wat hoger kan dan de huidige meting dan heb ik ruim marge. Het is dan niet nodig TinyUsb te gebruiken.

Usb blijft voor mij een moeilijk ding. Als pc eindgebruiker is het meestal plug and play. Op een microcontroller heb je geen OS dat de bitjes netjes op een rij zet. Meestal is het zoeken naar software die iemand anders daarvoor heeft geschreven. Daar geldt de uitspraak: "een goed geschreven code begrijpen is vaak moeilijker dan een slecht programma schrijven".

Vriendelijke groeten,

Eduard

16-bit audio is effectief 44100 x 4 = 176400 bytes (ongeveer 1 Mbit) per second. Geen enkel probleem voor USB 1.1

USB is inderdaad nogal complex. Dat geldt voor iedereen die er in duikt. Voor Audio moet je een class Audio device bouwen in de PICO zodat de PC ziet dat hij audio data kan sturen.

USB heeft daar een standaard voor. Zie https://www.usb.org/sites/default/files/audio10.pdf

Hensz

Golden Member

Op 8 juni 2021 13:51:52 schreef deKees:
16-bit audio is effectief 44100 x 4 = 176400 bytes (ongeveer 1 Mbit) per second. Geen enkel probleem voor USB 1.1

Dat zou ik niet willen zeggen. CD branders met USB 1.1 hadden destijds grote moeite om voldoende data naar de brander te sturen om het e.e.a. succes te laten hebben. Je computer tegelijkertijd ook nog iets anders laten doen was garantie voor een falende burn.

Don't Panic!
Arco

Special Member

Da's vaak het probleem ook.
Oversturen van de data is zinloos als de processor niet genoeg 'vrije tijd' heeft om er iets zinnigs mee te doen en te verwerken.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Dat verhaal dateert uit de tijd dat er min of meer synchroon naar de CD geschreven moest worden. En al heel snel was schrijven op "1x" snelheid achterhaald en kon dat ook 2x, 4x of 8x. En DAN zit je ineens voorbij wat USB KAN, dus op USB zou het best kunnen dat je 4x kon schrijven, maar dat je dan wel "alles goed" moet doen om geen buffer underruns in de writer te krijgen.

USB heeft speciale voorzieningen voor situaties waarbij een afgesproken hoeveelheid data per seconde getransporteert moet worden. Dus juist "CD branden" is iets wat goed zou moeten gaan. Of op z'n minst niet falen DOOR USB.

[Bericht gewijzigd door rew op dinsdag 8 juni 2021 19:28:39 (23%)

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Eduard2

Golden Member

Beste forumleden,

Via ttyACM0 is de snelheid te klein om met audio aan de slag te gaan.

int main() {
char eenstr[100], nulstr[100];
for(int i=0; i<99; i++){eenstr = '1'; nulstr = '0';};

FILE *fp;
fp = fopen("/dev/ttyACM0", "w");

for(int j=0; j<10000; j++) {
fputs(nulstr,fp);
fputs(eenstr,fp);
} // end for

fclose(fp);
return(0);
}

Deze test vraagt 58 seconden om vanaf de pc tienduizend keer 200 charakters naar de pico te schrijven. Als ik deze keer geen telfout maak dan komt dat neer op ongeveer 35000 bytes per seconde. Dat is te weinig voor audio. Ik ga nogeens uitpluizen of het met heel grote buffers sneller kan. Vermoedelijk zal er niets anders opzitten dan TinyUsb te leren gebruiken.

Vriendelijke groeten,

Eduard

Arco

Special Member

Hi speed data transfers zijn wat lastiger met USB. Hier staat e.e.a. beschreven: https://www.beyondlogic.org/usbnutshell/usb1.shtml

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

USB werkt met pakketten data. Max 1 pakket per milliseconde. De max data hangt af van het soort transfer. Een TTY werkt met interrupt transfers, die op USB1.1 full speed (12Mbit) een max payload hebben van 64 byte. Met 1 Packet per milliseconde zit je dan vast aan 64Kb max per seconde.

Audio werkt met isochrone transfers, omdat timing belangrijk is. Dan heb je max 1023 bytes per pakket, en vervalt error correctie. En dus ook max 1 Mbyte per seconde data transfer.

En dat gaat niet over een TTY verbinding. Daarvoor moet je in de PICO een audio driver implementeren op je USB engine, en ook op de PC een audio kanaal openen.

.

[Bericht gewijzigd door deKees op woensdag 9 juni 2021 11:53:02 (100%)

Op 9 juni 2021 11:52:03 schreef deKees:
USB werkt met pakketten data. Max 1 pakket per milliseconde. De max data hangt af van het soort transfer. Een TTY werkt met interrupt transfers, die op USB1.1 full speed (12Mbit) een max payload hebben van 64 byte. Met 1 Packet per milliseconde zit je dan vast aan 64Kb max per seconde.

Dat klopt kennelijk niet, want ik haal 153kb/sec.

code:


getafix:~> time cat test123.dat > /dev/ttyACM1 
0.012u 0.000s 0:07.15 0.1%      0+0k 0+0io 0pf+0w
getafix:~> wc test123.dat
  10000   20000 1100000 test123.dat
getafix:~> bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
1100000/07.15
153846.15384615384615384615

Dit is met een STM32F072 als target, dus het zegt niet dat het met een PICO zo hard kan, maar ik verwacht van wel. De pico CPU is 1 tikje moderner (M0+ ipv M0) en bijna 3x sneller (133 ipv 48MHz).

Eduard,

Je gebruikt nogal slechte methodes om throguhput te testen. Het zou best kunnen dat je systeem vindt dat een fputs naar het device "serial port" direct verstuurd moet worden, dus dat ie regelt dat er direct een "100 byte string" verstuurd wordt. Dat zou dan een 64+36 byte pakket worden, waarbij de rest van het 36-byte-pakket ineens geen mogelijkheid meer voor is om dat te benutten.

Daarnaast je testprogramma bevat een essentiele fout.

Ik snap niet dat je compiler er mee accoord gaat, maar je bedoel waarschijnlijk:

eenstr = '1';

waar nu

eenstr = '1';

staat. Daarnaast moeten die strings afgesloten worden. Op zijn minst:

eenstr[99] = '\0';

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Eduard2

Golden Member

Dag Rew,

De gcc compiler gaf geen foutmelding. Een string moet met eindnul worden afgesloten. Achteraf heb ik dat aangepast en ook de stringlengte tot 1000 charakters verhoogd. Dat werkt en geeft nauwelijks een verschil in snelheid.

Ik twijfel of de pico op dat punt sneller is dan uw STM32F072. De pico heeft twee PLL's. De ene levert de systeemklok die standaard 125 MHz bedraagt. (max van de chip is 133 MHz). De tweede PLL levert 48 MHz voor de USB.

Met uw testmethode lijkt de pico wel een slak met opgetrokken handrem. 31500 char/sec is het beste resultaat. Mijn testfile heeft 20000 lijnen met 64 char. Alle char, uitgezonderd het regeleind, zijn '1'. De beste timing is iets meer dan 38 seconden.

Vriendelijke groeten,

Eduard

[Bericht gewijzigd door Eduard2 op woensdag 9 juni 2021 17:20:06 (23%)

Ik heb even:
* Pico SDK geinstalleerd.
* een test programma geschreven.
* gemeten.

Mijn pico haalt 450 kbyte per seconden over CDC. De jouwe is kapot.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Hensz

Golden Member

Lijkt me leuk om jou testprogramma eens door Eduard te laten runnen. Zijn testje is niet erg efficiënt, dus als jullie met hetzelfde programmaatje dezelfde doorvoer krijgen, dan weten we dat ie toch niet kapot is en idd ruimschoots snel genoeg gaat voor wat Eduard er mee van plan is. :)

Don't Panic!
Eduard2

Golden Member

Dag Rew,

Is uw testprogramma beschikbaar ? Graag had ik dezelfde proef genomen. Als mijn pico defect zou zijn dan zal dat vlug aan het licht komen. Ik heb er nog een paar. Het lijkt me vreemd dat de pico door een elektrisch defect te langzaam zou worden. Een foute instelling of niet de juiste software versie lijkt me waarschijnlijker. Mogelijk deugt het programma dat ik op de pico installeerde niet.

Intussen probeerde ik verdere foutoorzaken uit te sluiten. Teneinde de pc uit te sluiten herhaalde ik de test op een laptop met Lubuntu. Zelfde resultaat. Doe ik mogelijk iets fout met het gebruik van de usb ? Moet de pico worden gemount ? Dat heb ik niet gedaan.

Vriendelijke groeten,

Eduard

[Bericht gewijzigd door Eduard2 op donderdag 10 juni 2021 09:17:14 (23%)

c code:

/**
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"

char buf[1028];

int main() 
{
  int i;

    stdio_init_all();
    memset (buf, '.', 1024);
    buf[1022] = '\r';
    buf[1023] = '\n';
    buf[1024] = 0;
    for (i=69;i<1024;i+=70)
       buf[i] = '\n';

    for (i=0;i<10;i++) {
        printf("Hello, world! %d\n", i);
        sleep_ms(1000);
    }
    for (i=0;i<10240;i++) {
        sprintf (buf, "block %d.......\r\n", i);
        memset (buf+12, '.', 12);
        printf ("%s", buf);
    }

    return 0;
}

1Mbyte was te snel voor mij om met de hand te meten. Dus 10Mbyte doet er ongeveer 22 sec over op mijn computer/pico.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Eduard2

Golden Member

Bedankt rew,

Je zou het niet geloven maar het is waar. Uw usb is een haas en de mijne blijft een slak. Aan de pc kant testte ik zowel met: time cat /dev/ttyACM0 als met Serial portterminal. Om de test redelijk kort te houden verkleinde ik naar 1 MByte. 1 MByte vraagt ongeveer 100 seconden.

Intussen heb ik de proef hernomen. Een tweede pico geeft hetzelfde resultaat. Een andere pc idem. We kunnen dus een defect aan pc of pico uitsluiten.
Alle componenten behalve de ontwikkelingsomgeving zijn intussen veranderd en toch blijft usb hier ondermaats presteren.

Hoe compileer je ? Ik gebruik geen Visual studio maar de commandline. Bij de installatie op de pc heb de Getting Started gevolgd. Ik overweeg alle bestanden te verwijderen en opnieuw te installeren.

Vriendelijke groeten,

Eduard