Augmenter la rapidité de communication entre Arduino Due et Raspberry Pi 3

Bonjour à tous,

j’ai établie une connexion entre mon Arduino Due et ma raspberry pi 3 par liaison USB Native. Mon Arduino doit envoyer 200.000 données par seconde. Cependant à la réception (Raspberry Pi) mon temps d’execution est de 9s c’est beaucoup trop long car mon arduino échantillonne un ADC à 200.000/s. je veux donc envoyer les échantillons (mot de 16 bits) le plus rapidement possible.

Voici mon code Arduino :

#include <SPI.h>
#define CS_1865 10

void setup()
{
SerialUSB.begin(115200);
while(!SerialUSB);
SPI.begin(10);
SPI.setClockDivider(10, 12);
}
void loop()
{
int i=0;
int tab[20000];
long tstart, tstop ;
while(i<20000)
{
SerialUSB.println (Read1865());
i=i+1;
}
}
int Read1865()
{
byte msb;
int lsb;
msb = SPI.transfer(10, 0xA0) ;
lsb = SPI.transfer(10, 0x00);
return ((int) msb) <<8 | lsb;
}

Mon code en Python pour raspberry :

import serial
import time

start_time = time.time()

ser = serial.Serial(’/dev/ttyACM3’, 115200)
i=0
liste = [200000]
while i<200000 :
liste.append(ser.read(7))
i=i+1
print(liste[20])
print(“Temps d execution : %s secondes —” % (time.time() - start_time))

Merci pour votre aide

Plusieurs accélérateurs possibles:

Utiliser si possible un diviseur de fréquence moindre dans SPI.setClockDivider(10, 12); pour obtenir une fréquence plus élevée,

Utiliser la bibliothèque TurboSpi pour Sam3x (jusqu'à 42 MHz),

Transférer les données avec des tampons de par exemple 256 octets avec SerialUSB.write((uint8_t*)buffer, 256); au lieu des SerialUSB.print() plus lents. La limitation viendra peut-être du pi 3.

Salut

Tout d'abord, en PYTHON je doute de la ligne suivante :

liste = [200000]

Cette ligne ne dimensionnera pas ta liste à 200000 éléments. Elle initialise ta liste avec un élément valant 200000.

Pars plutôt d'une liste vide :

liste = []

Ensuite la méthode append() ajoute un élément à la liste.

Ensuite avec une vitesse de 115200 baud, chaque bit prend 8.68 µs pour être émis. Avec 8 bits + 1 bit de start + 1 bit de stop, chaque octet prend 86,8 µs pour être émis. Tu atteindra donc au maximum 11520 octets à la seconde.

Même avec un baudrate de 1Mb/s ce sera impossible.

A moins que je n'aie pas compris l'énoncé ...

@+

Coté arduino DUE, le baudrate en SerialUSB n'est pas pris en compte, mais il faut en mettre un différent de 0. Le périphérique UOTGHS va aussi vite qu'il le peut et selon la programmation qui a été faite (ici en l'occurrence celle de SerialUSB qui est loin d'être optimisée) mais atteint toutefois ~ 850 KBytes/s avec des SerialUSB.print.

Je pense qu'il faut considérer la chose d'un peu plus haut que par le niveau technique de la vitesse de la liaison.

200.000 données par seconde ?? C'est juste énorme. C'est quoi ces données ? Il me semble assez peu probable qu'un couple DUE + Raspberry soit en mesure de gérer un tel flux.

En supposant que chaque donnée pèse un seul tout petit octet, ça fait un flux de 700 Mo par heure, soit 16 Go par jour. On est pratiquement au niveau d'un flux video (compressé), mais je ne pense pas que ce soit le cas ici.

Par exemple, plusieurs vagues hypothèses : a) ces données ont vocation à être stockées individuellement => sur quel support côté rapsberry ? Certainement pas une SD CARD qui va rendre l'âme très vite. b) ces données sont agrégées par un calcul côté raspberry => pas assez puissant pour faire ça en plus de gérer la réception. c) ces données ne sont ni stockées ni agrégées, elles servent simplement à surveiller l'état d'un système avec un haut niveau de réactivité => déporter une partie de la surveillance (gestion de seuil ...) au niveau DUE

Effectivement la vitesse en baud n'a pas d'influence sur le temps d’exécution de mon script en python.

ard_newbie: Plusieurs accélérateurs possibles:

Utiliser si possible un diviseur de fréquence moindre dans SPI.setClockDivider(10, 12); pour obtenir une fréquence plus élevée,

Utiliser la bibliothèque TurboSpi pour Sam3x (jusqu'à 42 MHz),

Transférer les données avec des tampons de par exemple 256 octets avec SerialUSB.write((uint8_t*)buffer, 256); au lieu des SerialUSB.print() plus lents. La limitation viendra peut-être du pi 3.

Je ne peux pas augmenter la fréquence de la clock SPI car a hautes fréquence je ne peux plus échantillonner ça va trop vite. la limite c'est SPI.setClockDivider(10, 12).

Pouvez vous me donner des exemple sur la bibliothèque TurboSpi en reprenant mon code

Et enfin moi j'envoie des mots de 16 bits. J'ecrit donc SerialUSB.write((uint8_t*)buffer, 2) ?

ard_newbie: Coté arduino DUE, le baudrate en SerialUSB n'est pas pris en compte, mais il faut en mettre un différent de 0. Le périphérique UOTGHS va aussi vite qu'il le peut et selon la programmation qui a été faite (ici en l'occurrence celle de SerialUSB qui est loin d'être optimisée) mais atteint toutefois ~ 850 KBytes/s avec des SerialUSB.print.

Comment je peux optimiser le SerialUSB s'il vous plait ?

Je vous remercie tous pour vos réponses !

Effectivement, une description plus précise du projet permettrait sans doute d'y voir plus clair.

Puisque ton capteur cale déjà à la fréquence actuelle du SPI, c'est inutile de passer sur TurboSpi.

Pour info, modifier SerialUSB (donc le driver du périphérique USB OTG HS) pour le rendre nettement plus rapide demanderait plusieurs semaines (voire plusieurs mois) à une équipe performante, c'est probablement la raison pour laquelle Arduino ne l'a pas fait. Toutefois il est déjà utilisable en l'état pour transmettre 1 million d'échantillons uint16_t par seconde avec des SerialUSB.write() vers un PC. C'est à la fois beaucoup et très peu si on le compare à l'horloge du périphérique qui est de 480 MHz.

Pourquoi ne pas utiliser l'un des hardware serial pour transmettre vers le pi 3 (Serial1,Serial2,etc…) avec lesquels tu peux très facilement augmenter le baudrate jusqu'à plusieurs millions de bauds par seconde.

D'autre part, le logiciel qui tourne sur le pi 3 est écrit en python, et pour ce que j'en sais, il s'agit d'un langage interprété, donc relativement lent (à confirmer avec ceux qui l'utilisent). La lenteur est peut-être de ce coté-ci.