SPI : RPi en mode esclave ? Alternatives ?

Des infos, des conseils sur les bus DSI,CSI, I2C, SPI... du Raspberry Pi

Modérateur : Francois

Pinhapple
Raspinaute
Messages : 125
Enregistré le : jeu. 23 févr. 2017 15:53
Localisation : Rouen

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par Pinhapple » jeu. 13 juil. 2017 11:26

spourre a écrit :Oh put* le c*n, j'ai failli lire autre chose :lol: :lol: :lol:
J'ai pas envie de savoir mais je pense savoir quand même ! :lol:
spourre a écrit :Tu as bien compris ma proposition (honnête).
Tu peux aussi avoir une autre approche:
Le SPI du Raspberry peut gérer 2 esclaves , par un signal CS (chip Select). Tu peux utiliser ce signal pour demander la transmission à intervalle régulier (timer ? thread ?). C'est mieux que le polling et c'est le Pi qui garde le contrôle.
Les broches 24 et 26, respectivement SPI_CE0_N et SPI_CE1_N ? J'ai mon branchement sur la 0 actuellement.
Le souci du timer qui vient à l'esprit, c'est qu'il y a un risque de décalage : si je demande une transmission toutes les n microsecondes mais que le signal est légèrement décalé, je risque de louper le coche à un moment. :?
spourre a écrit :Dans le sens Arduino (5V) vers Pï (3.3V), un pont diviseur est suffisant.
Dans le sens Pi (3.3V) vers Arduino (5V), tu n'as pas besoin de pont diviseur mais, comme dé"jà expliqué (hé hé), il y a un risque de mauvais fonctionnement très difficile à déceler: En logique CMOS les niveaux H(ight) et L(ow) sont définis respectivement à 2/3 et 1/3 de Vcc (alimentation). Entre ces 2 niveaux, il y a indétermination, et le circuit peut prendre n'importe quel état.
Oui, je me souviens bien de ton explication du inférieur à 1/3 pour le LOW, supérieur à 2/3 pour le HIGH, et le flou entre deux. ;)
Pour l'instant dans mes tests, ça communique sans souci visible en tout cas. Si ça venait à poser problème, comment corriger ça ? (je pense à l'inverse d'un pont diviseur de tension, un "pont multiplicateur de tension" ? :D )
  • RPi 3 + LibreELEC / RPi 3 + RetroPie / RPi B+ + Sense HAT ou Framboisedorf ou module caméra
  • Arduino Mega, Uno, Nano
  • Freescale FRDM KL25Z

destroyedlolo
Raspinaute
Messages : 1583
Enregistré le : dim. 10 mai 2015 18:44
Localisation : Dans la campagne à côté d'Annecy
Contact :

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par destroyedlolo » jeu. 13 juil. 2017 14:39

Yo !
spourre a écrit :Côté Arduino, le programme (ou la thread) qui traite les signaux, fait le calcul et remplit le buffer de transmission, termine en mettant une pin (à déterminer) à 1 puis 0.
Là, côté PI, c'est un cas idéal d'utilisation d'interruption : comme ca, pas besoin de faire du polling bouffeur de CPU.

Pour la conversion 3.3 <-> 5.v, il y a aussi des "level shifter" tout fait à base de mosfet et qui ne coutent que quelques centimes. Souvent utilisé par exemple pour les bus I2C.

A+
  • BananaPI : Gentoo, disque SATA de 2 To
  • Domotique : 1-wire, TéléInfo, Tablette passée sous Gentoo, ESP8266
  • Multimedia par DNLA
  • Et pleins d'idées ... et bien sûr, pas assez de temps.
Un descriptif de ma domotique 100% fait maison.

spourre
Raspinaute
Messages : 735
Enregistré le : lun. 22 déc. 2014 16:50
Localisation : 67380 LINGOLSHEIM

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par spourre » jeu. 13 juil. 2017 16:49

destroyedlolo a écrit : ...
Pour la conversion 3.3 <-> 5.v, il y a aussi des "level shifter" tout fait à base de mosfet et qui ne coutent que quelques centimes. Souvent utilisé par exemple pour les bus I2C.

A+
Toutafé.
Sinon, le moindre petit transistor qui traîne au fond de la boîte à malices peut convenir.

Je ne sais si notre ami alimente son Arduino à partir du 5 V du Pi, mais ça peut aussi éviter que les 2 alims dérivent en sens inverse, même en restant dans la tolérance:
Celle du 5V à 5 V et des poussières, Celle du 3.3V à 3.3V - des poussières ==> risque indétermination du niveau O ou 1 fournit par le Pi.

Sylvain

spourre
Raspinaute
Messages : 735
Enregistré le : lun. 22 déc. 2014 16:50
Localisation : 67380 LINGOLSHEIM

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par spourre » jeu. 13 juil. 2017 17:09

Pinhapple a écrit : ...
Les broches 24 et 26, respectivement SPI_CE0_N et SPI_CE1_N ? J'ai mon branchement sur la 0 actuellement.
Le souci du timer qui vient à l'esprit, c'est qu'il y a un risque de décalage : si je demande une transmission toutes les n microsecondes mais que le signal est légèrement décalé, je risque de louper le coche à un moment. :?
)
Oui, sur mes docs, il y a bien CE indiqué , le E vient de Enable.
Qu'as-tu branché dessus côté Arduino ? Normalement, il n'y a pas de donnée qui transiste dessus, juste un changement d'état pour dire quel est l'esclave interrogé.

Il me semble que tout au début de nos échanges, pour des problèmes de rapidité justement (écriture vers la SD), Bud t'avait suggéré un tampon (buffer) circulaire .
Évidemment, si le Raspberry est trop chargé et que l'Arduino pédale trop vite, ça finira par une perte de données.
D'où l'intérêt d'alléger au maximum le PI en faisant maigrir son OS et en le déchargeant de l'acquisition/conversion des signaux.

On retombe sur la problématique bien évoquée dans l'autre discussion (UDP) de la volumétrie et du débit (liaison ET traitement)..
Destroyedlolo y a bien rappelé la problématique et les éventuelles solutions. J'avais aussi lourdement insisté sur le choix de la bibliothèque pour pousser le Pi dans ses retranchement avant de se lancer dans le RT ou le driver dans le kernel ( voire passer au bare metal).
Ce sont des piste intéressantes mais trop compliquées à explorer dans le peu de temps qu'il te reste.
Tu pourrais esayer la lib bcm qui est moins sexy que libwiringpi mais qui est, du coup, plus proche du hard. Même si maintenant tu as de bons réflexes en C + lib, ça reste un gros morceau à avaler (j'ai pas encore sauter le pas).
Sylvain

Pinhapple
Raspinaute
Messages : 125
Enregistré le : jeu. 23 févr. 2017 15:53
Localisation : Rouen

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par Pinhapple » mar. 1 août 2017 14:26

Bonjour !

Quelques nouvelles : les communications I2C et série ont été éliminées, preuves à l'appui ; l'Ethernet également à cause d'un manque de fiabilité du shield fourni (marche, marche pas, marche, marche pas, etc.), donc de retour en SPI.

Dans un premier temps, je suis reparti de zéro avec un petit soft simple : j'envoie un mot, j'en reçois un autre ; j'ai choisi d'envoyer "Hello" et de recevoir "World", pas très original, mais les mots possèdent 5 caractères chacun, donc bien pratique pour du SPI.

J'ai un soft en C sur le RPi qui utilise WiringPi :

Code : Tout sélectionner

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPiSPI.h>

#define SPI_CHANNEL 0
#define SPI_SPEED   1000000 // Hz.

int main(void)
{

	wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED);

	while (1)
	{

		char buf[5] = {'H', 'e', 'l', 'l', 'o'};

		printf("Sending   : %s\n", buf); // Censé afficher "Hello".

		wiringPiSPIDataRW(SPI_CHANNEL, buf, 5);

		printf("Receiving : %s\n\n", buf); // Censé afficher "World".

		sleep(1);

	}

	return 1;

}
Et le soft Arduino :

Code : Tout sélectionner

#include <SPI.h>

char receivingBuffer[5];
char sendingBuffer[5] = {'W', 'o', 'r', 'l', 'd'};

volatile char bytes_received = 0;

volatile boolean process_it = false;

void setup()
{
  
  Serial.begin(230400);

  SPCR |= bit(SPE);

  pinMode(MISO, OUTPUT);

  SPI.attachInterrupt();

  SPDR = sendingBuffer[bytes_received];

}

ISR(SPI_STC_vect)
{

  receivingBuffer[bytes_received] = SPDR;

  if (++bytes_received == 5)
  {

    bytes_received = 0;

    process_it = true;

  }

  SPDR = sendingBuffer[bytes_received];

}

void loop()
{
  
  int i, c;

  if (process_it == true)
  {

    receivingBuffer[bytes_received] = 0;

    Serial.print("Receiving : ");
    Serial.println(receivingBuffer); // Censé afficher "Hello".
    Serial.print("Sending   : ");
    Serial.println(sendingBuffer); // Censé afficher "World".

    bytes_received = 0;

    process_it = false;
    
  }

}
Ce code Arduino est basé sur une question posée sur Stack Exchange.

Comme spécifié par mes commentaires, je souhaite envoyer "Hello" à l'Arduino, tandis que celui-ci me répond "World". J'ai compris comment fonctionnait la fonction wiringPiSPIDataRW(), à envoyer le contenu d'un tableau tout en recevant le contenu d'un autre, et de les permuter index par index (je m'acharnais à tenter d'utiliser sa valeur de retour...).

Avec ce code en l'état, j'envoie "Hello" et le reçoit sur l'Arduino, mais alors que je pense renvoyer "World", c'est "WHell" qui revient sur le RPi. :?

Auriez-vous une indication sur la provenance de ce curieux résultat ?

:!: Je poste ici pour rester dans mon sujet sur le SPI et ne pas trop m'éparpiller, mais je reconnais que c'est peut-être plutôt un problème de code, donc dites-moi si je dois poster ailleurs ! ;)
:!: C'est peut-être aussi un problème d'Arduino, mais comme je pense que le problème vient de mon algo, on reste dans du C. Pareil, je posterai ailleurs si ça n'a pas sa place ici ! ;)

EDIT : passer la fréquence du SPI de 1 000 000 Hz à 100 000 Hz corrige le souci. Reste à voir si je peux trouver une fréquence entre ces deux valeurs qui me permettra de transférer mes données dans le temps imparti !

A ce propos, j'ai calculé qu'il me fallait un débit de transfert d'au moins 524 288 bit/s pour tout transférer en temps et en heure ; pourriez-vous m'aiguiller sur une correspondance bit/s <-> Hz afin que je puisse choisir une fréquence de SPI suffisante ? Pour l'instant je suppose que c'est comme pour l'I2C, avec 1 Hz = 1 kbit/s.
  • RPi 3 + LibreELEC / RPi 3 + RetroPie / RPi B+ + Sense HAT ou Framboisedorf ou module caméra
  • Arduino Mega, Uno, Nano
  • Freescale FRDM KL25Z

spourre
Raspinaute
Messages : 735
Enregistré le : lun. 22 déc. 2014 16:50
Localisation : 67380 LINGOLSHEIM

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par spourre » mer. 2 août 2017 12:25

Pinhapple a écrit :Bonjour !

....
A ce propos, j'ai calculé qu'il me fallait un débit de transfert d'au moins 524 288 bit/s pour tout transférer en temps et en heure ; pourriez-vous m'aiguiller sur une correspondance bit/s <-> Hz afin que je puisse choisir une fréquence de SPI suffisante ? Pour l'instant je suppose que c'est comme pour l'I2C, avec 1 Hz = 1 kbit/s.
Bonjour,

Ma réponse va être toute théorique , en me basant que sur ma compréhension du protocole.
Pour moi, le SPI est un protocole simple, pour ne pas dire dire simpliste.
Il n'y a aucun adressage "in band" (comprendre dans le flux transféré. Le seul adressage que je constate est dans la possibilité de sélectionner l'esclave par le signal CS .
Il n'y a pas de checksum, parité ou autre. C'est un transfert orienté "bit" et il appartient aux couches supérieures de prévoir les éventuelles corrections, acquittements ou réémission.

Comme c'est un protocole nativement bidirectionnel, chaque front d'horloge (montant ou descendant selon le mode SPI choisi), déclenche le transfert d'un bit.

AMHA, dans le meilleur des cas, le débit en bit par seconde est égal à la fréquence d'horloge.

Nota: pour l'I2C, je ne vois pas comment tu arrive au résultat 1Hz = 1 kbit/s mais c'est peut-être HS.

Bon courage pour ta dernière ligne droite.

Sylvain

Pinhapple
Raspinaute
Messages : 125
Enregistré le : jeu. 23 févr. 2017 15:53
Localisation : Rouen

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par Pinhapple » mer. 2 août 2017 12:37

spourre a écrit :AMHA, dans le meilleur des cas, le débit en bit par seconde est égal à la fréquence d'horloge.
Sachant que c'est le maître qui impose la fréquence, ce serait du 1,2 GHz au mieux ? Mais du coup, je suppose que l'Arduino et son horloge à 16 MHz seront limitées à cette fréquence.
spourre a écrit :Nota: pour l'I2C, je ne vois pas comment tu arrive au résultat 1Hz = 1 kbit/s mais c'est peut-être HS.
Dans mes recherche sur l'I2C, j'ai toujours trouvé les mêmes chiffres selon les modes (100 k, 400 k, 1 M, 3,4 M, 5 M), mais avec des unités différentes (Hz et bits/s), donc j'en ai déduit que dans le cas de l'I2C, ces deux unités étaient équivalentes.

De plus, cette réponse sur Stack Exchange indique que 1 Hz = 1 bit/s, pour du SPI.
spourre a écrit :Bon courage pour ta dernière ligne droite.
Merci beaucoup ! :)
  • RPi 3 + LibreELEC / RPi 3 + RetroPie / RPi B+ + Sense HAT ou Framboisedorf ou module caméra
  • Arduino Mega, Uno, Nano
  • Freescale FRDM KL25Z

spourre
Raspinaute
Messages : 735
Enregistré le : lun. 22 déc. 2014 16:50
Localisation : 67380 LINGOLSHEIM

Re: SPI : RPi en mode esclave ? Alternatives ?

Message par spourre » mer. 2 août 2017 12:59

Pinhapple a écrit :
spourre a écrit :AMHA, dans le meilleur des cas, le débit en bit par seconde est égal à la fréquence d'horloge.
Sachant que c'est le maître qui impose la fréquence, ce serait du 1,2 GHz au mieux ? Mais du coup, je suppose que l'Arduino et son horloge à 16 MHz seront limitées à cette fréquence.
....

De plus, cette réponse sur Stack Exchange indique que 1 Hz = 1 bit/s, pour du SPI.
....
ATTENTION: Quand je parle "horloge" pour un bus (SPI, I2C, UART...), je parle de l'horloge du bus, qui est rarement celle du CPU. En général, il y a un ou des pré-diviseurs.

C'est bien, comme toujours, je constate que tu n'attends pas un résultat "tout cuit" et que tu cherches par toi-même. Au moins, cette deuxième source corrobore mon analyse et te confirme que pour le SPI, un front d'horloge déclenche le transfert d'un bit.

Après, entre la théorie et la opratique, il y a tout un monde. Le contrôleur SPI du Pi a ses limites, celui de l'Arduino aussi et, au dessus, il y a les couches logicielles (dont la libwiringpi) qui rajoutent de la latence. Quand tu montes en fréquence, le dessin du PCB et le câblage joue aussi un rôle important.

Pour le reste, je ne vais pas te noyer de considération sur la valence du code et la rapidité de modulation et Nyquist. Ici les signaux n'ont que 2 états logiques (0 et 1) et, en poremière approximation, on peut poser que le débit en bit/s et la fréquence (en Hz) sont exprimés par le même nombre.

Sylvain

Répondre

Retourner vers « Les BUS interfaces »