Gamoover

[move]Le staff Gamoover vous souhaite la bienvenue ;)

[WIP] Réalisation d'un déguisement pour mon fils

Démarré par tilowil, Lundi 31 Mars 2014, 23:23:13 PM

gc339

Citation de: spectroman le Mercredi 09 Avril 2014, 22:41:29 PMJe connais pas du tout les arduinos, mais ne peux tu pas utiliser le port SPI pour écrire sur AS1107?
^-
Le repos, c'est fait pour les jeunes. Ils ont toute la vie devant eux. J. Gabin/M. Audiard





spectroman

Après lecture du code AS1107.cpp, pour augmenter la vitesse de transfert, tu dois faire deux modifications :

1) Le SPI est fait en bit-bang logiciel (fonction shiftOut), fait le faire par le HARDWARE, ça sera beaucoup plus rapide.

Pour cela, il faut utiliser la classe SPI.

D'après la page 8 du datasheet (rev 2.28) de l'AS1107, l'AS1107 fonctionne avec :

Une horloge qui doit être à 0 lors du /CS et les données sont mémorisées sur front montant.
D'après http://fr.wikipedia.org/wiki/Serial_Peripheral_Interface, c'est le mode 0.

Le MSB est transferé en premier.

La fréquence Max de l'AS1107 est de 10MHz, comme celle de l'arduino est à 16MHz, il faut donc diviser par 2 l'horloge de ce périphérique.

2) l'autre problème c'est que les AS1107 sont en série.
Du coup, tu dois toujours envoyer 5 * 16 bits au lieu de 16!

Pour diminuer les temps d'accès connecte tes AS1107 en parallèle.

Côté matériel :
- câble la PIN 51 MOSI sur l'entrée DIN de tous les AS1107
- câble la pin 52 (SCK) sur l'entrée clock de tous les AS1107
- câble une pin /CS (au choix) par AS1107 (à connecter sur LOAD/CSN)
- ne câble pas les DOUT

au total tu dois connecter 7 signaux.

Côté logiciel :

tu ajoute ça dans ta classe AS1107 dans AS1107.h :

byte CS_Array[NbMod];

tu modifie AS1107.c comme ca :

AS1107::AS1107(byte cspin0, byte cspin1, byte cspin2, byte cspin3, byte cspin4)
{
byte i;

CS_Array[0] = cspin0;
CS_Array[1] = cspin1;
CS_Array[2] = cspin2;
CS_Array[3] = cspin3;
CS_Array[4] = cspin4;

for (i = 0; i < NbMod; i++) {
pinMode(CS_Array[i], OUTPUT);
digitalWrite(CS_Array[i], HIGH);
}

SPI.begin(); /* il n'est pas précisé si il faut faire begin avant ou après
             * la config. Donc il faut peux être modifier l'ordre */
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setBitOrder(MSBFIRST);
}

// ------------------------------------------------------------------------------------
// Writes Data to a Register of the AS1106/AS1107
// chip: Number of the controller chip (starting at 0 for the left)
// reg:  Register of the controller
// data: Data to be written
void AS1107::WriteRegister( byte chip, byte reg,  byte data)
{
if (chip >= 0 && chip < NbMod) {
digitalWrite(CS_Array[chip], LOW);

SPI.transfer(reg);
SPI.transfer(data);

digitalWrite(CS_Array[chip], HIGH);
}
}


Je n'ai pas testé le code, il doit y avoir des bugs, mais c'est juste pour te faire voir l'idée.

Le fait de passer de série en parallèle va augmenter ta vitesse de 500%, et tu dois avoir un gain du même ordre en passant d'une gestion logiciel à une gestion matériel.

a+


tilowil

wouah !

je vais faire le test ce soir.

hier soir j'ai suivi l'idée d'usagi, d'utiliser les Fast PWM, mais la vitesse n'a pas évoluer. Même  si la bibliothèque digitalWriteFast est dite écrire 10x plus vite sur les ports digitaux.

a suivre.

gc339

Citation de: spectroman le Jeudi 10 Avril 2014, 12:21:53 PMLe fait de passer de série en parallèle va augmenter ta vitesse de 500%, et tu dois avoir un gain du même ordre en passant d'une gestion logiciel à une gestion matériel.

Je ne vois pas comment tu peux gagner du temps avec ce genre de parallélisation étant donné que les AS1107 partagent un même bus SPI et qu'ils doivent être adressés individuellement. Cela serait vrai s'ils devaient recevoir les mêmes données, dans ce cas ils pourraient être adressés simultanément. 
Le repos, c'est fait pour les jeunes. Ils ont toute la vie devant eux. J. Gabin/M. Audiard





spectroman

Citation de: gc339 le Jeudi 10 Avril 2014, 13:41:11 PM
Je ne vois pas comment tu peux gagner du temps avec ce genre de parallélisation étant donné que les AS1107 partagent un même bus SPI et qu'ils doivent être adressés individuellement. Cela serait vrai s'ils devaient recevoir les mêmes données, dans ce cas ils pourraient être adressés simultanément. 

Quand les matrices sont en série, il faut envoyer 5 * 16 bits à chaque qu'un registre est écrit.


void AS1107::WriteRegister( byte chip, byte reg,  byte data)
{
   if (chip>=0 && chip <= HighestCtrlNum) {
     chip = HighestCtrlNum -chip;
     digitalWrite(_cspin,LOW);
     for (int i=0; i<=HighestCtrlNum; i++) {
     if (i == chip) {
       shiftOut(_datapin, _clkpin, MSBFIRST, reg);
       shiftOut(_datapin, _clkpin, MSBFIRST, data);
     }
     else {
       shiftOut(_datapin, _clkpin, MSBFIRST, Registers::NoOp);
       shiftOut(_datapin, _clkpin, MSBFIRST, 0);
     }
   }
     digitalWrite(_cspin,HIGH);
   }
}


Ex: Quand la classe écrit un registre sur deux matrices :
80 bits sont envoyés pour modifier le 1er registre
80 bits sont envoyés pour modifier le 2eme registre

Quand les matrices sont en //, on peut les adresser individuellement, cette opération devient :
16 bits sont envoyés pour modifier le 1er registre
16 bits sont envoyés pour modifier le 2eme registre

On passe d'une écriture "par page" (et qui ne modifie qu'une donnée à la fois) à une écriture à accès aléatoire.

L'autre optimisation serai de faire une écriture "par page" qui modifie plusieurs données à la fois, mais c'est beaucoup plus dure à faire. Il faudrait faire deux tampons vidéo intermédiaires, comparer leurs différences et optimiser le transfert pour chaque matrice.


tilowil

Je vais essayer ce soir l'idée de Spectroman.

Mais de toute façon il faut que je monte les AS1107 ainsi :

gc339

Je viens de réparer une omission en parcourant le datasheet de l'AS1106/1107.

Donc pour rafraichir un affichage complet de 5 matrices de 8×8 LED's connectées en cascade, il faut 5 fois 8 trames de 16 bits.
A une fréquence de 10 Mhz, un renouvellement complet de l'affichage peut s'effectuer en 64 µs (15625 fois/secondes), à une fréquence de 8 MHz (celle de l'Arduino ÷2 ) cela correspond à 80 µs soit 12500 fois/seconde.
La fréquence de rafraichissement serait donc de 625 à 500 fois plus élevée que la persistance rétinienne minimum de 25 fois/seconde.

Alors pourquoi ne pas procéder par interruptions. L'Arduino devrait être en mesure de générer une interruption dés que le registre de transmission SPI est vide, il serait alors rechargé avec le nouveau mot à transmettre prélevé dans un tampon circulaire de 40 fois 16 bits et cela indéfiniment.
Ceci implique d'écrire la routine d'interruption en assembleur pour pouvoir maitriser sa durée d'exécution car elle ralentira sensiblement la vitesse de rafraichissement de l'affichage.

Le processus d'affichage serait ainsi asynchrone vis à vis de la classe qui n'aura plus qu'à écrire épisodiquement dans le tampon circulaire sans s'occuper de rien d'autre car il sera scruté cycliquement par la routine d'interruption.

Peut-être sera-t-il nécessaire de prévoir deux tampons pour éviter des parasites d'affichage indésirables, un tampon actif scruté par l'affichage et un tampon passif en cours de modification par la classe.
Deux flags sont alors nécessaires :

  • Le premier pour désigner le tampon actif parmi les deux, uniquement modifié par la classe.
  • Un deuxième flag de handshake :

    • Resetté par la classe juste après avoir modifié le premier.
    • Positionné dès que la routine d'interruption a effectivement changé de tampon. La classe devra attendre le positionnement de ce deuxième flag pour commencer à écrire dans le tampon passif.
Le changement effectif de tampon peut être différé jusqu'au qu'au moment où la routine d'interruption va accéder à sa première ligne, (celle qui correspond à la première colonne du premier afficheur ) pour éviter un affichage intempestif en plein milieu des afficheurs. Ce n'est qu'à partir de ce moment là que la routine pourra modifier le flag de handshake pour autoriser la classe à écrire dans le tampon passif.
Le repos, c'est fait pour les jeunes. Ils ont toute la vie devant eux. J. Gabin/M. Audiard





spectroman

Citation de: tilowil le Jeudi 10 Avril 2014, 16:58:22 PM
Je vais essayer ce soir l'idée de Spectroman.

Mais de toute façon il faut que je monte les AS1107 ainsi :


Pourquoi, tu as déjà fait ton PCB?

Attention, pour essayer le montage //, il te faut une sortie d'arduino pour chaque LOAD/CSN des AS1107.

Il te faut 7 signaux :
SCK
MOSI
/CS_MTRX0
/CS_MTRX1
/CS_MTRX2
/CS_MTRX3
/CS_MTRX4

et le GND et le +5V bien sur ;)



tilowil

#40
Citation de: spectroman le Jeudi 10 Avril 2014, 12:21:53 PM
1) Le SPI est fait en bit-bang logiciel (fonction shiftOut), fait le faire par le HARDWARE, ça sera beaucoup plus rapide.

Pour cela, il faut utiliser la classe SPI.

2) l'autre problème c'est que les AS1107 sont en série.
Du coup, tu dois toujours envoyer 5 * 16 bits au lieu de 16!
[...]
Côté matériel :
- câble la PIN 51 MOSI sur l'entrée DIN de tous les AS1107
- câble la pin 52 (SCK) sur l'entrée clock de tous les AS1107
- câble une pin /CS (au choix) par AS1107 (à connecter sur LOAD/CSN)
- ne câble pas les DOUT

au total tu dois connecter 7 signaux.

Côté logiciel :

tu ajoute ça dans ta classe AS1107 dans AS1107.h :

byte CS_Array[NbMod];

tu modifie AS1107.c comme ca :

AS1107::AS1107(byte cspin0, byte cspin1, byte cspin2, byte cspin3, byte cspin4)
{
byte i;

CS_Array[0] = cspin0;
CS_Array[1] = cspin1;
CS_Array[2] = cspin2;
CS_Array[3] = cspin3;
CS_Array[4] = cspin4;

for (i = 0; i < NbMod; i++) {
pinMode(CS_Array[i], OUTPUT);
digitalWrite(CS_Array[i], HIGH);
}

SPI.begin(); /* il n'est pas précisé si il faut faire begin avant ou après
             * la config. Donc il faut peux être modifier l'ordre */
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setBitOrder(MSBFIRST);
}

// ------------------------------------------------------------------------------------
// Writes Data to a Register of the AS1106/AS1107
// chip: Number of the controller chip (starting at 0 for the left)
// reg:  Register of the controller
// data: Data to be written
void AS1107::WriteRegister( byte chip, byte reg,  byte data)
{
if (chip >= 0 && chip < NbMod) {
digitalWrite(CS_Array[chip], LOW);

SPI.transfer(reg);
SPI.transfer(data);

digitalWrite(CS_Array[chip], HIGH);
}
}

Le fait de passer de série en parallèle va augmenter ta vitesse de 500%, et tu dois avoir un gain du même ordre en passant d'une gestion logiciel à une gestion matériel.
Je comprends plus ou moins ou tu veux en venir. Mais si j'envoie les mêmes datas a toutes les matrices (tous les Din monté en //), ce sera le CS qui va dire sur quel Chipset je dois faire l'affichage, alors je n'aurais qu'un seul afficheur à la fois. Le principe me semble bon pour certains éléments d'animations comme le Cylon, mais pour les scrollings de texte si j'envoie les mêmes datas à tout le monde je vais devoir recouper mon buffer de 80 colonnes en 5 buffers de 8 colonnes et le transfert de ces 5 buffers vers les AS1107. en utilisant par exemple :

data[0]=0;
data[1]=0;
data[2]=0;
data[3]=0;
data[4]=0;

for (i=0;i<=79;i++)
{
 data[i/16]=data[i/16]+buffer[i]
}

for(i=0;i<=4;i++)
{
 // En simplifiant
 digitalWrite(CS_Array[i], LOW);
 SPI.transfer(reg[i]);
 SPI.transfer(data[i]);
 digitalWrite(CS_Array[i], HIGH);
}



Vite fait, si j'ai bien compris ou veux en venir Spectroman.

Citation de: spectroman le Jeudi 10 Avril 2014, 17:26:49 PM
Pourquoi, tu as déjà fait ton PCB?

Attention, pour essayer le montage //, il te faut une sortie d'arduino pour chaque LOAD/CSN des AS1107.

Il te faut 7 signaux :
SCK
MOSI
/CS_MTRX0
/CS_MTRX1
/CS_MTRX2
/CS_MTRX3
/CS_MTRX4

et le GND et le +5V bien sur ;)

Oui j'ai déjà des PCB, mais si besoin je peux en refaire d'autre.
Le but de mon montage était simplement d'avoir un minimum de fils qui passe dans le casque. il y aura déjà suffisamment de fils pour les matrices, les animations lumineuses des oreilles et du coté de la visière. A l'origine les oreilles et les sides devaient être fixe (j'ai aussi les PCB), mais j'ai trouvé ça triste, alors je vais les refaire sur de la veroboard. donc si le pilotage dela matrice doit être refait je referais les PCB.

Après pour les 7 fils, oui j'ai bien compris. J'ai juste mis ce câblage pour te faire voir ce que j'ai actuellement.


tilowil

Hier je n'ai pas trop travailler le projet, Y a un groupe de fadas qui nous a mis un teasing de la mort qui tue, et comme il a été super original je n'ai pas pu m'empecher d'y participer. Il a fallu choisir entre le teasing et la programmation et bien j'ai choisi... Le teasing (Moment de détente)  ^-^.

spectroman

Fada c'est le bon mot. Il est bien de chez nous.
Maintenant au boulot. ;)

tilowil

Le projet est en stand by pour une durée courte, j'espère.

Stay tuned.