ha attends j'ai dit une bêtise, tu peux pas le faire ça le pont diviseur de tension, "il débite du courant du coup ça marche pas"...
l'idée serait d'avoir un 5V bien propre et même un peu plus, c'est pas très gênant, le tout étant de pas griller les shift registers (74 HC 595? j'ai plus ta référence...) et surtout bien stable. le truc c'est que ce genre de choses nécessitent un peu de matériel... à tout hasard t'aurais pas un régulateur de tension 7805 et 2 gros condos qui trainent sous la main? (sinon ne t'embête pas à acheter, c'est pas très cher, mais le résultat est pas garanti alors... on cherchera d'autres pistes avant)
quel genre de matériel as-tu chez toi? je veux dire par là matériel de mesure électrique (voltmetre, oscilloscope, analyseur de trames, etc?
Oui ce sont des 74HC595, pour le 7805 et 2 gros condo je doit pouvoir trouver ça, 1000uF ça te parait assez gros? Niveau matériel j'ai un voltmètre de disponible, le reste je n'ai pas
J'ai aussi fait le test de brancher un interrupteur sur l'alim générale, quelle sois via arduino ou pile. Et lorsque que je coupe cette alim, les leds sont quand même allumées très très faiblement, donc apparemment le courant de sorties des pins traverse le circuit de manière à éclairé les leds, peut être que celà pose problèmes aussi? Car ça ne devrais pas être le cas non? Il doit y avoir un moyen de supprimer ce courant ?
- Edité par CactusTribe 23 octobre 2013 à 12:23:34
oui pour moi ça vient aussi du circuit, ton code est on ne peut plus propre et simple. et donc tu dis que tu as mis un interrupteur sur le bloc piles, c'est ça?
(les condensateurs, plus petits tu as? un seul condensateur de 10µF sur la sortie du régulateur suffirait, comme en entrée c'est des piles.)
pour l'instant ton bloc piles alimente quoi exactement?
avant de regarder les montages d'alim (parce qu'on en est même pas sûrs que ça vient de là), ce qu'il faudrait déterminer c'est d'où vient le problème: des transistors, t'en as combien? 1 par couche + 1 par colonne? seulement 1 par couche? encore moins?
en tout cas, il faudrait mesurer les tensions des couches "qui produisent beaucoup de fantomes" par rapport à la valeur qu'elles sont censées avoir: pour ça essaye de n'allumer qu'une diode ou deux (enfin selon ton programme, qui fait quand même le balayage, le but étant de chercher d'où viennent les fantômes, il vaudrait mieux qu'il y en ait), pareil pour les colonnes, la tension entre les colonnes et le 4.5V (ou 0, je me rappelle plus du sens de ton montage, le but étant que si ça marche bien, il y ait 0V sur le voltmetre).
Alors entre temps j'ai réussis à supprimer l'effet fantomes en reliant les masses des shift registers à l'arduino, avant elles étaient reliées au - de la pile.
Je récapitule les différents branchements du montage :
Vcc + MR des 595 ------> + Pile
OE + GND des 595 ------> GND Arduino
Sorties 595 colonnes (8+8) ------> Anodes LEDs
Collecteurs des 4 transistors ------> Cathodes LEDs
Bases des 4 transistors ------> Sorties 595 étages (4)
Emeteurs des 4 transistors ------> - Pile
Mesures :
V colonnes ON = 0.47
V colonnes OFF = -0.75
V étages ON = -0.83
V étanges OFF = -1.0
Toute ses mesures effectuées quand le programme des 2leds fonctionne.
Je n'ai plus les effets de fantomes donc, mais du coup le fait de passé en alimentation séparé ne permet pas (à ce stade) d'augmenté la luminosité des leds lors d'un affichage important de pixels.
ha mais t'avais pas relié les masses arduino et pile ensemble? désolé de pas l'avoir mieux dit avant, alors
CactusTribe a écrit:
Alors entre temps j'ai réussis à supprimer l'effet fantomes en reliant les masses des shift registers à l'arduino, avant elles étaient reliées au - de la pile.
mais... plus de fantomes, plus de problèmes?
bon plus sérieusement, je vais aller voir mieux comment fonctionnent les 74HC595 et je te dis mieux dès que j'ai fini. maintenant, pour moi c'est plus qu'un problème de programme. (ton truc d'écrire les leds une par une dans les registres là ça me parait pas OP comme truc)
Justement si j'avais relié les masses arduino et pile, et je viens de les séparé ce qui as permis d'enlever les fantomes !
Le problème de base était la luminosité des LEDs, l’hypothèse était que l'usb n'alimentais pas suffisamment, maintenant avec la pile on peut voir que ça ne change rien au problème x)
Si jamais tu connais l'ULN2803 (réseau de transistor) j'en ai à disposition si sa peut être plus opti ?
C'est vrais que le code est pas forcément opti, mais je n'ai pas trouvé une autre façon de faire, je suis débutant tout de même haha, j'ai pas tout les reflexes et tout n'est pas très claire dans ma tête
- Edité par CactusTribe 23 octobre 2013 à 19:17:58
bon. alors si tu as la masse de l'arduino sur les 74HC... il faudrait que tu leur donne aussi l'alimentation de l'arduino. sinon c'est pas beau^^
en fait, j'ai l'impression que quand tu "allume beaucoup de diodes", ton programme est assez lent pour que la luminosité soit moins bonne... essaye de rajouter DelayMicroseconds(10) dans ta fonction affichage pixel, n'importe ou, et lance un programme qui est censé afficher beaucoup de led et qui utilise cette fonction.
déjà, j'ai une idée: écrivons le programme pour être tout le temps dans le pire des cas: créer un tableau de booléens à 3 dimensions, ajouter l'état de la led à commander comme parametre de ta fonction affichage pixel, et balayer TOUTES les leds en permanence.
donc pour résumer: en variable globale ou accessible via une référence ou un pointeur (je sais pas ce qui existe sur arduino pour passer un tableau sans en faire une copie en mémoire), un tableau:
cube [4][4][4] de booléens.
ta fonction affichage s'écrit maintenant comme ça:
void affichagePixel(int x, int y, int z, boolean etat)
{
clearRegisters(); //on commence par mettre tout le monde à 0
setRegisterPin(16 + z, etat); //le choix de la couche
setRegisterPin(x+y*4, etat); //la led à allumer
writeRegisters(); //met à jour les registres à décalages
}
J'arrive après la bataille, dommage, je pense que j'aurais pu faire gagner un peu de temps.
Pour l'affichage, néanmoins je conseillerais plutôt le code suivant
int z=0;
void loop ()
{
setRegisterPin(16 + z, HIGH); //le choix de la couche
for(x=0;x<4,x++)
{
for(y=0;y<4;y++)
{
setRegisterPin(x+y*4, cube[x][y][z]); //allumer les leds qui doivent l'être à ce niveau
}
}
writeRegisters(); //met à jour les registres à décalages
setRegisterPin(16 + z, LOW); // on dé-sélectionne la couche
z=(z+1)%4
sleep(1); //attendre 1 ms pour que les gens voient les LEDs allumées. Image 250Hz \o/
}
Il n'y a plus qu'à ajouter du code pour changer les LEDs qu'on veut voir allumées (le code qui vient modifier le tableau cube)
L'avantage de ce code, c'est qu'il divise par 16 l'impression de clignotement (et il multiplie par 16 le rapport cyclique d'allumage des LEDs, donc on a l'impression que les LEDs brillent plus)
Remace : Merci pour ton bout de code, j'ai essayer de le mettre en place sans succès j'avais une erreur : to few argument in fonction void affichePixel. J'avais bien créer le tableau boolean cube[4][4][4];pourtant
J'ai par contre réussis à plus ou moins faire marché celui de Natalaya malgré encore quelques soucis, c'est à dire que je n'arrive pas à afficher la led (0,0,1) par ex, le code affiche tout les x et y du niveau z = 1, le tout - une led (x=3;y=3). Cependant coté luminosité rien à redire, c'est exactement la bonne intensité visible sans aucun problèmes de scintillement !
La photo qui met en évidence le résultat :
Main :
void loop()
{
affichagePixel(0,0,1);
}
AffichagePixel :
void affichagePixel(int x, int y, int z)
{
int cube[4][4][4];
setRegisterPin(16 + z, HIGH); //le choix de la couche
for(x=0;x<4;x++)
{
for(y=0;y<4;y++)
{
setRegisterPin(x+y*4, cube[x][y][z]); //allumer les leds qui doivent l'être à ce niveau
}
}
writeRegisters(); //met à jour les registres à décalages
setRegisterPin(16 + z, LOW); // on dé-sélectionne la couche
z=(z+1)%4;
delay(1); //attendre 1 ms pour que les gens voient les LEDs allumées. Image 250Hz \o/
}
Cas particulier : au 3ème étage la led inactive à l'étage 2 (3;3) elle se met à clignoté de façon périodique x)
- Edité par CactusTribe 24 octobre 2013 à 13:42:37
natalya: en fait c'est un peu le genre de choses que je voulais arriver au final à lui faire faire, mais j'ai pas l'intuition de le faire en une fois^^ donc tu n'est pas du tout en retard. par contre, je vois un truc là dans ton programme, quand tu allume une led, tu ne l'éteins pas au "tour d'après", si?
et de ce que je vois, tu allume une couche à chaque fois non? donc pour un "petit cube" ça marche, mais pour cube plus un grand ça peut faire des consommations nettement plus grandes aussi (genre sur un 8x8x8 ça peut faire 64 LEDS à la fois, soit 1.2A)?
CactusTribe: regarde si ta led est pas grillée? (mets une autre led en parallèle de celle-ci, pas besoin de souder, juste mets la en contact avec les mêmes points (enroule les pattes autour des fils, en plus c'est une led du bord, te fais pas chier) et vois
toutes les leds (3,3,z) s'allument normalement, sauf celle-ci?
pour vérifier que c'est bien un probleme de code, essaye d'éditer ton programme pour donner à chaque tour de boucle les indices et valeur de led dans ton IDE
pour vérifier le programme de natalya, tu peux rajouter une ligne qui écrit dans ta console PC avec l'écriture des registres dans les boucles for. ça doit ressembler à ça, mais je suis pas sûr.
serial.write("x :" + x + "y: " + y + "z: "+ z +"\t"+ etat + "\n");
qui te permet de vérifier si le code de natalya écrit bien les bonnes choses dans les registres (j'ai quand même aucun doute là dessus, mais si tu veux vérifier tu peux^^).
ta fonction affichagePixel est très longue en durée, ça peut expliquer les clignottements périodiques. (sauf la colonne x=3 et y=3)
par contre, je vois un truc là dans ton programme, quand tu allume une led, tu ne l'éteins pas au "tour d'après", si?
Physiquement, le système ne peux allumer qu'un étage à la fois (sauf si tu affiches la même chose sur plusieurs étages). Je désélectionne bien mon étage en fin d'itération, et à chaque itération de loop je réécris toutes les valeurs de l'étage à afficher.
Par contre, j'ai oublié de déclarer x et y.
Mon code ressemblerait plutôt à ça :
int cube[4][4][4];
int z=0;
int loopCount=0;
void loop()
{
int x, y;
//On passe dans loop toutes les ms. Toutes les 1000 fois, donc toutes les secondes
//On va appler une fonction qui change le motif affiché.
if(loopCount==0)
updateCube();
loopCount= (loopCount+1)%1000;
// A partir de là, c'est le code qui allume régulièrement les LEDs
setRegisterPin(16 + z, HIGH); //le choix de la couche
for(x=0;x<4;x++)
{
for(y=0;y<4;y++)
{
//allumer les leds qui doivent l'être à ce niveau
setRegisterPin(x+y*4, cube[x][y][z]);
}
}
writeRegisters(); //met à jour les registres à décalages
setRegisterPin(16 + z, LOW); // on dé-sélectionne la couche
z=(z+1)%4; //On passe à la couche suivante pour le prochain passage dans loop
delay(1); //attendre 1 ms pour que les gens voient les LEDs allumées. Image 250Hz \o/
}
int currentLed = 0;
void updateCube()
{
//Pour tester le cube, on va allumer les LED une par une et changer de LED toutes
// les secondes
//D'abord on efface tout le cube (c'est plus simple que d'éteindre les LEDs qu'on
//a allumées avant.)
clearCube();
// On marque la LED qui nous intéresse pour être allumée
cube[currentLed%4][(currentLed/4)%4][currentLed/16] = HIGH;
// on passe à la prochaine LED pour quand cette fonction sera à nouveau appelée
// c'est à dire à peu près 1s plus tard
currentLed = (currentLed + 1)%64;
}
void clearCube()
{
int i,j,k;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
for(k=0; k<4; k++)
cube[i][j][k]=LOW;
}
Du coup, Cactus, j'attends tes questions sur le code ci-dessus. Si tu n'as pas de question, je t'en poserai, ça te permettra de voir tout se qui se cache dans ce code.
pour vérifier que c'est bien un probleme de code, essaye d'éditer ton programme pour donner à chaque tour de boucle les indices et valeur de led dans ton IDE
Son code est faux : les 0 en x et y qu'il passe en argument à affichagePixel sont écrasés dans la fonction et donc ignoré, seul le z est utilisé, et explique pourquoi l'étage 1 s'allume. Ensuite le cube physique s'allume en fonction des valeurs contenues dans la variable cube, qui ne sont pas initialisée. On aurait pu avoir un motif très différent avec le même code.
oui non mais du coup ce que je voulais dire c'est que tu (par volonté s'entend) n'allume pas diode par diode, mais étage par étage, du coup ça fait consommer 16*plus de courant (320mA) dans son cas actuel, mais ça fait aussi 64 x plus (1.2A) dans le cas d'un 8x8x8 comme il exprime l'idée d'en faire un au début du topic.
200 LEDs RGB donc 600 LEDs. Je simule le multiplexage sur une seule LED RGB (à anode commune). Je perçois un léger clignotement (ce qui ne devrait pas).
Le schéma elec est on ne peut plus simple, le +Vcc va sur l'anode, chaque cathode de LED va sur une résistance de 220 ohm qui va sur une sortie pwm.
J'ai testé en diminuant le max du compteur, en jouant sur le delay, la luminosité est faiblarde. (plein pot ça éclaire du feu de dieu).
Si quelqu'un a une idée ?
Merci.
PS : Je me rends compte que j’empiète sur le post d'un autre.
- Edité par Julien Grall 25 octobre 2013 à 0:27:49
Natalya : J'ai tester ton code, il fonctionne , il affiche toutes les leds une par une convenablement !
J'ai essayer de le décortiquer et de le comprendre mais quelques truc m’échappent encore, je n'arrive pas à visualisé clairement et précisément l'enchainement des actions.
Déjà % c'est bien le modulo du C ? Il permet de donner le reste de la division c'est ça?
Donc en appliquant cette opération j'ai essayer de remplacer les termes à certains endroit pour comprendre les résultats :
cube [1%4] [(1/4)%4] [1/16] = cube [0] [0] [0.065] ? (Ce résultat me parait bien étrange)
Si tu pouvais m'éclairer un peu la dessus
Car du coup j'ai essayer ensuite de tester différentes valeurs dans les boucles x et y, pour pouvoir ensuite recrée la fameuse fonction affichagePixel(x,y,x) qui me permettrais de créer plus facilement les animations. Mais sans succès.
Autre problème : Si je fais loopCount= (loopCount+1)%1; pour rafraichir plus rapidement et afficher donc la totalité des led, ça ne marche pas, on perçois seulement une diagonal du cube qui en plus scintille de façon très visible.
oui, % c'est modulo, soit le reste de la division euclidienne ENTIERE d'un entier par un entier:
int dividende - (int résultat * int diviseur) = int reste //qu'on appelle ici modulo
ça permet de pas faire des tonnes de boucles pour rien. (la syntaxe, c'est a%b= reste de la division entière de a par b)
du coup dans ta compréhension du modulo il y a un problème: déjà, (1+1)%1000, ça fait 2%1000, ça fait 2, pas 0, ni 1 (j'aime pas quand on écrit 2 = sur la même ligne, ça ôte tout le sens de la ligne).
ensuite, sur le même principe, cube[1%4][1/4%4][1/16] donne cube[0][0][0]: les divisions (barre de fraction) sur un int donnent la partie entière du résultat, et le modulo donne le reste. donc pour prendre l'exemple concret de la 2e coordonnée, 1/4%4 ça fait pareil que 0%4, ça fait 0.
du coup pour ta dernière question, (loopcount+1)%1 ça donne: reste de la division entière de loopcount+1 par 1. or quand tu divise un nombre par 1, le reste c'est 0. du coup ça fait update ton cube à chaque tour de la fonction loop, au lieu de faire 1000 tour entre chaque update.
sinon... là ça marche, avec le code de natalya, pourquoi chercher à le modifier? tout ce que tu as à faire, c'est de changer les valeurs dans le tableau cube quand il y a besoin, le programme fait TOUT le reste.
Je ne vois pas comment et où tu peut changer les valeurs du tableau?
Car exemple simple si je veux allumer tout le cube visuellement je doit faire tourner le code de Natalya assez vite pour l'illusion, sauf que j'ai jouer sur le modulo %1000 pour la vitesse, ou j'ai aussi jouer sur delay, également delayMicrosec et au final ça ne marche pas, scintillement visible.
pour sélectionner une led à afficher, ça se passe dans updateCube();
il y a 3 phases: la phase ou il vide le cube (ou le remplit de 0), la phase où il sélectionne les leds à allumer SUR TOUT LE CUBE, et la phase de sélection de l'image suivante
Natalya a écrit:
int currentLed = 0;
void updateCube()
{
//partie "vidange" du cube
clearCube();
/* sélection des leds à allumer
ici il choisit une seule led
en fonction de la valeur de currentLed*/
cube[currentLed%4][(currentLed/4)%4][currentLed/16] = HIGH;
/*sélection de la prochaine frame
qui dans ce cas précis passe par l'incrémentation de currentLed,
modulo 64, le nombre de leds du cube*/
currentLed = (currentLed + 1)%64;
}
Je vais modifier un tout petit peu mon code, comme suit :
int cube[4][4][4];
int z=0;
int loopCount=0;
void refreshLights()
{
int x, y;
// A partir de là, c'est le code qui allume régulièrement les LEDs
setRegisterPin(16 + z, HIGH); //le choix de la couche
for(x=0;x<4;x++)
{
for(y=0;y<4;y++)
{
//allumer les leds qui doivent l'être à ce niveau
setRegisterPin(x+y*4, cube[x][y][z]);
}
}
writeRegisters(); //met à jour les registres à décalages
setRegisterPin(16 + z, LOW); // on dé-sélectionne la couche
z=(z+1)%4; //On passe à la couche suivante pour le prochain passage dans loop
}
int currentLed = 0;
void updateCube()
{
//Pour tester le cube, on va allumer les LED une par une et changer de LED toutes
// les secondes
//D'abord on efface tout le cube (c'est plus simple que d'éteindre les LEDs qu'on
//a allumées avant.)
clearCube();
// On marque la LED qui nous intéresse pour être allumée
cube[currentLed%4][(currentLed/4)%4][currentLed/16] = HIGH;
// on passe à la prochaine LED pour quand cette fonction sera à nouveau appelée
// c'est à dire à peu près 1s plus tard
currentLed = (currentLed + 1)%64;
}
void clearCube()
{
int i,j,k;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
for(k=0; k<4; k++)
cube[i][j][k]=LOW;
}
void loop()
{
//On passe dans loop toutes les ms. Toutes les 1000 fois, donc toutes les secondes
//On va appler une fonction qui change le motif affiché.
if(loopCount==0)
updateCube();
loopCount= (loopCount+1)%1000;
refreshLights();
delay(1); //attendre 1 ms pour que les gens voient les LEDs allumées. Image 250Hz \o/
}
Voilà, comme ça, j'ai le moins de choses possibles dans loop.
Comment fonctionne ce code ? l'idée de ce code, c'est que le microcontrôleur est très rapide, et donc que le temps d'exécution des instructions est négligeable.
Du coup, dans loop, j'ai du code qui ne prend pas de temps, et un delay(1). Ma boucle va donc être appelée toutes les 1ms. Ca va me servir de base de temps. Une fois que j'ai choisi cette base de temps, je vais éviter de la changer, parce que ça a de l'influence sur toutes ce que je fais dans loop. Pourquoi ai-je choisi 1ms ? Il me faut un temps assez long pour pouvoir considérer que le reste du code s'exécute instantanément, et assez court pour que je puisse agir aussi souvent que je le veux. En plus, si c'est rond, c'est mieux : si j'avais choisi 7ms, je n'aurais pu agir que toutes les 7ms, ou toutes les 14, ou 21, ... C'est pas pratique.
Bon, du coup, qu'est ce que je fais dans loop ?
On travaille sur un cube lumineux, le but c'est donc d'allumer le cube. On sait qu'on ne peut allumer qu'un étage à la fois, et qu'il faut changer d'étage assez souvent pour que l'œil humain ait l'impression que tous les étages sont allumés en continu. On peut le faire toutes les ms. On va le faire à chaque passage dans loop, c'est ce que fais ma fonction refreshLights ci-dessus.
On voudrait bien changer le motif affiché par le cube. Par contre, ça, on ne va pas le faire aussi souvent, parce que sinon l'œil n'aura pas le temps de le voir. J'ai choisi de changer toutes les secondes, donc toutes les 1000 ms (toutes les 1000 loop). C'est à ça que sert le 1000 dans
loopCount= (loopCount+1)%1000;
Il faut lire ce code comme loopCount va maintenant valoir la valeur qu'il avait +1, et si ça fait 1000, à la place, loopCount repasse à 0. La ligne juste au dessus n'est executée que si loopCount vaut 0, donc une fois sur 1000, donc une fois toutes les 1000 ms.
Si tu veux changer ton cube plus ou moins souvent, c'est ce 1000 qu'il va falloir changer : c'est le nombre de passage dans la boucle où on ne change rien.
Et pour ma mise à jour du cube, j'efface tout mon cube (en fait j'efface le tableau dans la mémoire, mais c'est ce tableau qui sert à choisir quelles LED on allume dans refreshLights), et j'y écris mon nouveau dessin.
Bon, la ligne du milieu est vraiment bizarre. J'y reviens en dernier. Je voulais éclairer les LED une par une, il me fallait donc une variable qui compte de 0 à 63 (il y a 64 LED), en augmentant de 1 à chaque passage dans la fonction. C'est ce que je fais avec currentLed = (currentLed + 1)%64;.
C'est pas facile à voir avec un cube de 4x4x4. Imaginons que le cube fasse 10x10x10. Ca fait 1000 LED. En comptant de 0 à 999, je compte le nombre de LED. Pour savoir de quelle LED je parle, je vais utiliser le code suivant :
le premier chiffre sera le z
le second chiffre sera le y
le troisième chiffre sera le x
Par exemple, pour la LED 537, on a x=7, y=3, z=5.
Comment je récupère mes chiffres ? On est en division entière, donc le premier c'est facile
537/100=5 donc z=(numéro de la LED)/100
Le % permet de récupérer le reste de la division entière.
537/10=53, donc 537%10=7, donc x=(numéro de la LED)%10
Pour le y, on mélange les deux. On commence par virer le 7
537/10=53
et ensuite on garde le 3
53%10=3, donc y=(numéro de la LED/10)%10.
En remettant ça dans les indices du tableau, ça donne
Merci beaucoup pour tes explications ! Même si celà reste encore un peu flou forcément par le manque d'expérience et le fait que je suis pas l'auteur du code, j'ai pas répondus tout de suite car j'ai préféré prendre un peu le temps d'étudier jours après jours faire quelques test, laisser murir le truc on va dire.
J'ai donc réussis en modifiant un peu de façon empirique le code pour obtenir un rafraichissement non visible en allumant tout un étage d'un coup successivement de façon à obtenir un cube entier.
Cependant quand il s'agit de mettre en place par exemple de animations différentes qui s'enchaine à la suites avec un délais d'animation changeable comme dans mon code du début avec un nombre de cycles intégré à la fonction et ben je bloque total.
Voici le code actuel, qui décrit le cube entier dont je parle au début :
int currentLed = 0;
void updateCube()
{
//partie "vidange" du cube
clearCube();
/* sélection des leds à allumer
ici il choisit une seule led
en fonction de la valeur de currentLed*/
for(int y=0; y<4; y++)
{
for(int x=0; x<4; x++)
{
cube[x][y][currentLed/8] = HIGH;
}
}
/*sélection de la prochaine frame
qui dans ce cas précis passe par l'incrémentation de currentLed,
modulo 64, le nombre de leds du cube*/
currentLed = (currentLed + 1)%32;
}
void clearCube()
{
int i,j,k;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
for(k=0; k<4; k++)
cube[i][j][k]=LOW;
}
void loop()
{
//On passe dans loop toutes les ms. Toutes les 1000 fois, donc toutes les secondes
//On va appler une fonction qui change le motif affiché.
if(loopCount==0)
updateCube();
loopCount= (loopCount+1)%1;
refreshLights();
delayMicroseconds(1); //attendre 1 ms pour que les gens voient les LEDs allumées. Image 250Hz \o/
}
bon ben on va reprendre: currentLed c'est un sélecteur d'image, donc ce que tu peux faire c'est changer son modulo par ton nombre d'images (cube entiers). on va prendre comme exemple le fait d'afficher 1 plan horizontal à la fois en boucle, avec un intervalle de 0.5s pour qu'on ait le temps de voir mais que ça soit pas trop lent.
natalya t'a expliqué qu'un tour de boucle loop() dure "grossomodo 1ms" (tout est négligeable devant la temporisation pour fixer l'affichage) donc elle a rajouté une variable pour mettre à jour l'affichage moins souvent, en enlevant le scintillement dû au temps de mise à jour du cube. pour que ça soit visible par l'oeil, etc... il faut 500ms pour faire la temporisation qu'on veut, donc loopcount va être incrémenté "modulo 500":
loopCount= (loopCount+1)%500;
ensuite, il nous faut une fonction qui allume un plan:
maintenant, on compte combien on a d'images différentes à afficher. 4 plans horizontaux sur le cube, donc 4 images. donc on incrémente currentLed modulo 4 à la fin de la fonction updateCube:
currentLed = (currentLed + 1)%4;
du coup on obtient ça:
int cube[4][4][4];
int z=0;
int loopCount=0;
void refreshLights()
{
int x, y;
// A partir de là, c'est le code qui allume régulièrement les LEDs
setRegisterPin(16 + z, HIGH); //le choix de la couche
for(x=0;x<4;x++)
{
for(y=0;y<4;y++)
{
//allumer les leds qui doivent l'être à ce niveau
setRegisterPin(x+y*4, cube[x][y][z]);
}
}
writeRegisters(); //met à jour les registres à décalages
setRegisterPin(16 + z, LOW); // on dé-sélectionne la couche
z=(z+1)%4; //On passe à la couche suivante pour le prochain passage dans loop
}
int currentFrame = 0;
void updateCube()
{
//Pour tester le cube, on va allumer les LED une par une et changer de LED toutes
// les secondes
//D'abord on efface tout le cube (c'est plus simple que d'éteindre les LEDs qu'on
//a allumées avant.)
clearCube();
// On marque les leds qui nous intéresse pour être allumées dans l'image en cours.
plan_horizontal(currentFrame);
// on passe au prochain plan pour quand cette fonction sera à nouveau appelée
// c'est à dire à peu près 1s plus tard. on pourrait le faire en début de fonction
currentFrame = (currentFrame + 1)%4;
}
void clearCube()
{
int i,j,k;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
for(k=0; k<4; k++)
cube[i][j][k]=LOW;
}
void loop()
{
//On passe dans loop toutes les ms. Toutes les 500 fois, donc toutes les 500 millisecondes
//On va appeler une fonction qui change le motif affiché.
if(loopCount==0)
updateCube();
loopCount= (loopCount+1)%500; //%500 pour donner 500ms entre 2 changement d'image
refreshLights();
delay(1); //attendre 1 ms pour que les gens voient les LEDs allumées. Image 250Hz \o/
}
void plan_horizontal(int etage){
int i,j=0;
for(i=0, i<4,i++){
for(j=0,j<4,j++){
cube[i][j][etage] = HIGH; }
}
}
bon ben on va prendre un exemple simple, et le décomposer pour que tu comprenne comment te servir de ce que t'a donné Natalya. on va prendre comme exemple le fait d'afficher 1 plan horizontal à la fois en boucle, avec un intervalle de 0.5s pour qu'on ait le temps de voir mais que ça soit pas trop lent.
natalya t'a expliqué qu'un tour de boucle loop() dure "grossomodo 1ms" (tout est négligeable devant la temporisation pour fixer l'affichage) donc elle a rajouté une variable pour mettre à jour l'affichage moins souvent, (dans son exemple à elle, une fois toutes les secondes) ce qui a pour unique but d'enlever le scintillement dû au temps de mise à jour du cube.
pour notre exemple, il faut 500ms pour faire la temporisation qu'on veut, donc loopcount va être incrémenté "modulo 500":
loopCount= (loopCount+1)%500;
ensuite, il nous faut une fonction qui allume un plan horizontal (bon je te fais pas l'affront de t'expliquer comment elle marche...):
maintenant, on compte combien on a d'images différentes à afficher. 4 plans horizontaux sur le cube, donc 4 images: les images 0,1,2, et 3.
pourquoi incrémenter "au modulo"? quand currentFrame vaut 4, le modulo vaut 0, pour 5 c'est 1, pour 6 c'est 2, pour 7 c'est 3, etc, juqu'à la valeur maximale pour un int.
pour avoir une boucle 0,1,2,3 sur les images sans avoir à faire des tests sur la valeur de currentFrame, on incrémente currentFrame modulo 4 à la fin de la fonction updateCube:
int cube[4][4][4];
int z=0;
int loopCount=0;
void refreshLights()
{
int x, y;
// A partir de là, c'est le code qui allume régulièrement les LEDs
setRegisterPin(16 + z, HIGH); //le choix de la couche
for(x=0;x<4;x++)
{
for(y=0;y<4;y++)
{
//allumer les leds qui doivent l'être à ce niveau
setRegisterPin(x+y*4, cube[x][y][z]);
}
}
writeRegisters(); //met à jour les registres à décalages
setRegisterPin(16 + z, LOW); // on dé-sélectionne la couche
z=(z+1)%4; //On passe à la couche suivante pour le prochain passage dans loop
}
int currentFrame = 0;
void updateCube()
{
//Pour tester le cube, on va allumer les LED une par une et changer de LED toutes
// les secondes
//D'abord on efface tout le cube (c'est plus simple que d'éteindre les LEDs qu'on
//a allumées avant.)
clearCube();
// On marque les leds qui nous intéresse pour être allumées dans l'image en cours.
plan_horizontal(currentFrame);
// on passe au prochain plan pour quand cette fonction sera à nouveau appelée
// c'est à dire à peu près 1s plus tard. on pourrait le faire en début de fonction.
currentFrame = (currentFrame + 1)%4;
}
void clearCube()
{
int i,j,k;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
for(k=0; k<4; k++)
cube[i][j][k]=LOW;
}
void loop()
{
//On passe dans loop toutes les ms. Toutes les 500 fois, donc toutes les 500 millisecondes
//On va appeler une fonction qui change le motif affiché.
if(loopCount==0)
updateCube();
loopCount= (loopCount+1)%500; //%500 pour donner 500ms entre 2 changement d'image
refreshLights();
delay(1); //attendre 1 ms pour que les gens voient les LEDs allumées. Image 250Hz \o/
}
void plan_horizontal(int etage){
int i,j=0;
for(i=0, i<4,i++){
for(j=0,j<4,j++){
cube[i][j][etage] = HIGH;
}
}
}
EDIT: apparemment il y a une limite pour la taille des réponses (ce qui parait logique) du coup j'ai été obligé de faire un double-post
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.