Méthode fiable de transfert via USB depuis un PC (résolu avec un autre câble)

Bonjour
J'ai un PC connecté à un ESP32 par USB et qui le pilote pour contrôler des LEDstrips pour un projet de jukebox virtuel (lecture de MP3/de streams radio par internet/de CDs et, peut-être plus tard, de vidéos). Il y aura à la fin environ 1000 LEDs au total inégalement réparties sur 4 ports de l'ESP32, pour l'instant un peu moins. J'arrive à faire des effets gérés par l'ESP32 seul:

(La partie avec 4 lignes au dessus de l'écran sera remplie à la fin de LEDstrip 144LEDs/m)
Mais maintenant, j'aimerais pouvoir verser une image sur tout ou partie des LEDs présentes et donc que le PC envoie la valeur à mettre dans chaque LED concernée par la liaison USB (par exemple, une image d'un CD inséré dans la partie pas encore remplie quand on en insère un dans le lecteur).
Seulement j'ai fait des essais et les pertes lors du transferts sont systématiques (on est donc ici sur l'envoi d'environ 3000 bytes).
Est-ce qu'il y a une méthode fiable pour envoyer une telle quantité de données en étant sûr qu'on retrouve la même chose sur l'ESP32? J'ai cherché un peu sur le net, j'ai vu plein de "pour envoyer de grosses quantités, il faudra modifier la méthode", mais rien de bien explicite?
Merci
Cordialement
David

Bonjour,

S'il y a des pertes systématiques c'est qu'il y a un problème hard ou soft. le téléchargement des esp32 via usb (serie) envoie beaucoup plus de 3000 caractères et se passe sans problème (et en général sans réémission).

Ceci dit il existe de nombreux protocoles pour envoyer de grosses masses de données par exemple 'xmodem' qui a été très utilisé du temps des modems et est un peu tombé en désuétude avec les évolutions technologiques.

Merci de ta réponse.
C'est sûrement soft.
Je suis en 115200 bauds, est-ce que je peux allègrement passer en 921600?
Pour recevoir les données sur l'esp32, je fais du byte par byte (après avoir essayé la méthode readBytes pour avoir tout d'un coup):

byte GetSerialData(void)
{
    while (!Serial.available()) {};
    return Serial.read();
}

et côté Windows, pour envoyer, une fois connecté et ayant un (com)HANDLE avec CreateFile/GetCommState/SetCommState, j'utilise WriteFile.

Bonjour

Je suis en 115200 bauds, est-ce que je peux allègrement passer en 921600?

Cel dépend du circuit intégré d'interface USB présent sur la carte, pour l'ESP32 cela ne pose aucun problème.
Souvent un CH340 (certaines versions de ce CI acceptent 921600 bauds, pas toutes)
C'est donc à essayer.

Merci. On peut utiliser n'importe quelle valeur genre mettre "500000" (tant qu'on met la même pour le PC et l'ESP) ou il faut des valeurs normalisées?

Sinon la meilleure méthode pour recevoir reste le byte par byte via Serial.read() ou les ~3000 valeurs en même temps via Serial.readBytes()?

Vous pouvez metter toute valeur de débit acceptée par le deux appareils.

Aucune méthode de laison série ne transmet les octets 'en même temps', les octets (et même les bits) sont tranmis l'un après l'autre

Merci encore de votre réponse.
Donc je vais rester sur mes Serial.read() simples.
Je viens de faire un test où à chaque fois que l'ESP32 reçoit un trio de byte pour une couleur de LED, il envoie un chiffre avec le nombre de LEDs qui ont leur couleur en retour au PC et à chaque fois, ça s'arrête à 64 (donc 64*3=192 byte sont reçues par l'ESP32 quand j'en envoie 1956 actuellement au total).

Mets ton code.

Comme il n'y a pas de handshake tu peux potentiellement perdre des données si ton programme exécute du code en tâche de fond et que ladite tâche l'occupe un peu trop ou si tu traites un bloc de données alors que la transmission est toujours en cours.

En augmentant la taille du buffer , 64 par défaut, ça pourrait peut être aller plus loin

Plutot que d'augmenter la taille du buffer, il faut travailler le programme de réception.

Si on considère l'application envisagée, il doit y avoir moyen de gérer le truc sans avoir besoin d'un buffer énorme. D'autant que la quantité de données à recevoir n'est pas très importante et au pire il pourrait mettre toutes les données dans un tampon jusqu'à réception de la fin de trame avant de les traiter.

Le code côté PC pour l'envoi une fois le HANDLE obtenu:

bool scom_SendBytes(HANDLE comhandle, unsigned char* pBytes, unsigned int nBytes)
{
	DWORD bytesSend;
	COMSTAT status;
	DWORD errors;
	//Try to write the buffer on the Serial port
	if (!WriteFile(comhandle, (void *)pBytes, nBytes, &bytesSend, 0))
	{
		ClearCommError(comhandle, &errors, &status);
		err_AddErreur(L"Can't write to the Comm port");
		return false;
	}
	return true;
}

appelé dans le code principal avec:

scom_SendBytes(hComm, pLEDs, 1 + 3 * (JS_NLED_NICHE + JS_NLED_ARCHE + JS_NLED_SPECTRE + JS_NLED_NOTE));

(1 byte de commande, 3 bits par led des 4 sorties)

Côté ESP32 la fonction de lecture d'une couleur:

CRGB GetSerialColor(void)
{
  int R,G,B;
  while (!Serial.available()) {};
  R=Serial.read();
  while (!Serial.available()) {};
  G=Serial.read();
  while (!Serial.available()) {};
  B=Serial.read();
  return CRGB(R,G,B);
}

Appelé dans le code principal:

          for (ti=0;ti<N_LED_ARCHE;ti++) ArcheLEDs[ti]=GetSerialColor();
          for (ti=0;ti<N_LED_SPECTRE;ti++) SpectreLEDs[ti]=GetSerialColor();
          for (ti=0;ti<N_LED_NOTE;ti++) NoteLEDs[ti]=GetSerialColor();
          for (ti=0;ti<N_LED_NICHE;ti++) NicheLEDs[ti]=GetSerialColor();

Cette méthode est déjà plus ou moins conforme à ce que me conseille fdufnews, je transfère directement les données dans les buffers mémoire utilisés par FastLED.

Le PC est effectivement un peu occupé par des initialisations en même temps (ouverture d'une fenêtre OpenGL, tri alphabétique sur les titres et artistes des MP3 trouvés, etc...), mais rien d'insurmontable non plus. Par contre, comme l'ordi est un mini intégré dans le meuble du jukebox, je le commande via teamviewer depuis mon PC de bureau ce qui peut prendre pas mal de ressources.

Pour ce qui est d'augmenter la taille du buffer, c'est bien 3 fois plus de bytes qui sont effectivement reçus.

Quand je parlais de charge c'était à l'ESP que je pensais.
En effet si le PC est trop chargé, il va envoyer des paquets puis il fera des pauses mais pendant ce temps l'ESP devrait être en attente.
Par contre, si l'ESP est trop chargé, il est possible que des données soient perdues s'il y a un débordement du buffer de réception.
C'est assez facile à mettre en évidence, en ralentissant le débit les erreurs devraient disparaître.

Comme mon programme ESP32 fonctionne avec un principe de mode d'affichage, j'ai suivi vos conseils en me disant que si je transférais trop de donnés au µcontrôleur alors qu'il est en train de calculer son affichage dans un autre mode, il risquait de louper des données.
J'ai donc essayer de lui envoyer un simple byte pour lui annoncer que l'ordi va lui transférer des données, qu'il arrête alors de calculer quoi que ce soit, qu'il envoie 2 bytes comme aknowledgement et se mettre en attente des données envoyées par l'ordi, que l'ordi n'envoie les données que quand il a reçu l'ACK, mais malgré tout, l'ESP ne reçoit pas toutes les données. Je n'ai pas encore regardé s'il reçoit plus qu'avant. Par contre, en mode debug sur l'ordi, j'ai bien vu que ce dernier recevait bien les 2 bytes d'ACK '<'+'>'.

Bon je suis sincèrement désolé du temps perdu, je viens par dépit de changer le câble USB et ça fonctionne maintenant sans souci. Je sais que j'aurais dû y penser avant, mais je transfère des données via le premier câble sans problème et je téléverse même le croquis à 921600 bauds avec ce même câble. Mais l'autre câble a résolu le problème. Désolé encore.

Happy end, c'est l'essentiel !

Par rapport au titre du fil de discussion on retient que le câble joue un rôle de premier plan la fiabilité du transfert

Oui, j'ai ré essayé avec l'ancien câble et clairement, ça ne marche pas avec.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.