Gamoover

LA VIE DU SITE - LES NEWS => Le Bistrot de l'Arcade => Discussion démarrée par: tilowil le Lundi 31 Mars 2014, 23:23:13 PM

Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Lundi 31 Mars 2014, 23:23:13 PM
Bonjour à tous,

Vous me direz que vient faire ce message dans le forum Gamoover ?
Et je vous répondrais que le déguisement à un lien avec le plus grand film consacré au jeu vidéo. Plus exactement avec les auteurs de la musique de la suite du film culte. Voyez vous de qui je parle ?
Le déguisement porte sur une seule personne et doit servir pour Halloween 2014.

J'ai déjà un petit peu avancé le projet seul et à partir de maintenant je partage cette réalisation avec vous, si les modérateurs sont d'accord pour voir un tel sujet traité sur Gamoo.

Les exigences de mon fils étaient très spécifique.
Il voulait la version avec afficheur et jeux de lumière.

J'ai trouvé les plans pour la réalisation et à partir de la il y avait une condition siné qua non réussir à faire une matrice de leds. Il fallait que je réussisse à piloter 5 matrices de 64 leds (8x8). Donc pour réussir j'avais le choix entre 3 composants (à ma connaissance) le Maxim Max7219, le Max7221 et l'Austria microSystem AS1107. Le but étant d'afficher des informations sur la série de matrices de leds. Pour envoyer les informations aux composants d'affichage, j'ai préféré utiliser un Arduino. Pour le moment je suis encore en plein test. Les résultats ne me conviennent pas encore. L'avantage de ces 3 circuits c'est que les informations ne se transmettent que par 3 fils (Clock, Data in, et Load).

Mon problème actuel c'est que mes matrices ne s'allume plus toutes. Tant que j'en avais 1, 2, 3 l'affichage se faisait mais avec 4 ou 5 lorsque trop de leds sont  allumés, le nombre de matrice redescend à 1, car la sortie +5v de l'Arduino est très limitée. Donc pour les essais avant de créer la visière je cherche comment associer une alimentation externe (j'utilise une alimentation de bornes avec la sortie +5V/Gnd) pour alimenter le module avec, et l'Arduino avec le port USB.
Mais quand je fais ce montage masse commune ou pas l'affichage marque n'importe quoi, comme si du parasitage venait perturber le signal 'Data in'. Pourtant j'ai mis 2 condensateurs entre le +5 et la masse pour filtrer.
Sinon j'ai aussi préparé mes circuits pour les oreilles, les cotés et la gestion des matrices.
Une fois ce point réglé, je vais percer la visière pour y insérer les matrices de leds.

Pour le moment je n'ai pas beaucoup de photos car le projet en ai encore au début.

Je cherche aussi une bonne adresse pour un traitement de surface (je vais avoir un chromage à faire faire, pour finaliser le projet). Le chromage doit se faire sur de la fibre de verre recouverte de résine (type résine urethane). Il faudra qu'il soit le proche de la perfection, car il va y avoir des petits détails que je suis en train de préparer qui ne souffriront pas un chromage médiocre.

Mais je n'irai pas plus loin si je n'arrive pas à afficher correctement, car c'est cette partie qui fera tout le charme du déguisement et qui donnera le coté réel au déguisement.

Si les supers forts en électronique pouvait me donner une piste de recherche pour mes problèmes d'alimentation, sachant qu'au final tout sera sur de la batterie pour être portable et que je voudrais utiliser la même batterie pour alimenter l'Arduino, les ventilateurs, les jeux de lumières fixes des oreilles et coté, et enfin l'affichage des matrices de leds.

Je poste aussi ce message car j'ai pu voir certain message utilisant des Arduino pour des jeux de lumières, voire même des gestion de digits 7 segments et donc ma problématique pourrait servir à d'autres personnes.

Merci pour vos commentaires et votre aide.


Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: SLEK le Lundi 31 Mars 2014, 23:51:39 PM
Salut,

Sacré projet, y en a un qui va être content !  ^-
Petite question au passage, comment ton fils verra à travers la visière avec tous ces modules à leds ???  ;D

@+
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Mardi 01 Avril 2014, 00:02:20 AM
Salut.
Citation de: SLEK le Lundi 31 Mars 2014, 23:51:39 PM
Sacré projet, y en a un qui va être content !  ^-
Merci. On sera 2 a être content. Lui pour son déguisement et moi pour y être arriver. Je pense que quand le projet sera abouti, plusieurs messages vont pleuvoir pour faire cette réalisation. C'est un grand classique très recherché, mais très compliqué à faire. Mais je n'en dirai pas plus, car si je n'arrive pas à faire le premier niveau le reste ne sert à rien.

Citation de: SLEK le Lundi 31 Mars 2014, 23:51:39 PM
Petite question au passage, comment ton fils verra à travers la visière avec tous ces modules à leds ???  ;D
Comme je fabrique ma propre matrice de leds, il va y avoir des espaces entre chaque led. En plus pour eviter qu'il ai un retour de lumière dans les yeux (par l'arrière des leds), je les ai peinte en noir (l'arrière des leds). Mais c'est vrai que pour le moment je travaille avec des modules de leds du commerce sur breadboard.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Mardi 01 Avril 2014, 06:17:12 AM
super projet.

Citationle Maxim Max7219, le Max7221 et l'Austria microSystem AS1107
tu as choisis lequel?

Citationmasse commune ou pas
La masse commune est obligatoire entre tes alimentations.

CitationPourtant j'ai mis 2 condensateurs entre le +5 et la masse pour filtrer
Il te faut aussi plusieurs condensateurs juste a coté de chaque Max7219.


as tu un schéma et des photos de ton montage?
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Mardi 01 Avril 2014, 10:35:27 AM
Citation de: spectroman le Mardi 01 Avril 2014, 06:17:12 AM
super projet.
Citation de: spectroman le Mardi 01 Avril 2014, 06:17:12 AM
Citation
le Maxim Max7219, le Max7221 et l'Austria microSystem AS1107
tu as choisis lequel?
Pour le moment je fait mes tests avec 5 Max7221, mais au final je préférerais utiliser l'AS1107 car il a des fonctions supplémentaires par rapport au Maxim et il va me permettre de lui envoyer des caractères pré-programmer alors qu'avec les Maxim je suis obligé de définir un pattern d'affichage a chaque scroll que je veux faire ou à chaque effet de lumière. Les brochages du boitier étant les mêmes une fois que je serais sur de mon montage avec les Maxim, je les remplacerai par des AS. Les Max7221 me serviront ensuite pour les oreilles et le coté de la visière.
Ma preference pour les AS1107 vient de leur compatibilité complete avec les Max7221/7219, du fait qu'ils sont moins cher et qu'ils ont plus de fonctions (petit lien (http://forum.arduino.cc/index.php/topic,14176.0.html) )
et voici ce qu'il est possible de faire avec 3 matrices pilotées par 3 AS1107.


Citation de: spectroman le Mardi 01 Avril 2014, 06:17:12 AM
La masse commune est obligatoire entre tes alimentations.
Il te faut aussi plusieurs condensateurs juste a coté de chaque Max7219.
Oui je l'ai fait mais regarde les photos plus bas. Je vais tenter avec une alimentation de PC aujourd'hui, comme l'Arduino peux être alimenter sur sa prise secteur en +7v à +12v, actuellement je l'alimente en +9v avec une pile. Je me disque mon alimentation de borne n'est peut être pas suffisamment fiable.

Les condensateurs pêchent peut être car actuellement il n'y en a que 2 a coté de l'arrivée du +5V/Gnd, mais à terme j'ai prévu le même couple de condensateur sur chaque PCB servant au pilotage de ma matrice. 5 matrices, 5 pcb de pilotage juste au dessus de chaque matrice et chaque PCB aura sa re
Citation de: spectroman le Mardi 01 Avril 2014, 06:17:12 AM
as tu un schéma et des photos de ton montage?
Le schema c'est le schéma de base pour une commande d'une matrice pilotée par un max7221 et avec des information qui arrive d'un arduino
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401094724-tilowil-MAX72XX-Schematic.jpg) (https://gamoovernet.pixhotel.fr/pics/20140401094724-tilowil-MAX72XX-Schematic.jpg)

Pour le moment j'ai câblé la Breadboard en prenant en compte que la partie pour la gestion d'une matrice de led.
Ce qui donne (alimentation par une pile de 9v, Arduino fournissant le +5v)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401094942-tilowil-IMG-4007.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401094942-tilowil-IMG-4007.JPG)
Je démarre la séquence (démarrage sur l'appui d'un bouton) pour le moment l'orientation n'est pas bonne mais ça c'est de la programmation ;) ).
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401095200-tilowil-IMG-4010.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401095200-tilowil-IMG-4010.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401095331-tilowil-IMG-4011.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401095331-tilowil-IMG-4011.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401100340-tilowil-IMG-4012.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401100340-tilowil-IMG-4012.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401100433-tilowil-IMG-4013.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401100433-tilowil-IMG-4013.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401100543-tilowil-IMG-4015.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401100543-tilowil-IMG-4015.JPG)
Donc il ne me reste plus que la matrice 2 d'allumée. Les autres n'affiche plus rien.

Maintenant alimentation par pile de 9v + alimentation externe (5V) masse commune même programme.
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401100728-tilowil-IMG-4046.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401100728-tilowil-IMG-4046.JPG)
Rien aucun affichage.

Alimentation par le prise USB Arduino fournissant le +5v
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401100950-tilowil-IMG-4057.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401100950-tilowil-IMG-4057.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101046-tilowil-IMG-4058.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101046-tilowil-IMG-4058.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101134-tilowil-IMG-4059.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101134-tilowil-IMG-4059.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101222-tilowil-IMG-4060.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101222-tilowil-IMG-4060.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101312-tilowil-IMG-4061.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101312-tilowil-IMG-4061.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101402-tilowil-IMG-4062.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101402-tilowil-IMG-4062.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101452-tilowil-IMG-4063.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101452-tilowil-IMG-4063.JPG)
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101552-tilowil-IMG-4116.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101552-tilowil-IMG-4116.JPG)
Comme toujours l'affichage commence bien puis au fur et a mesure le nombre de matrice decroit pour qu'il n'en reste qu'une seule (j'ai de la matrice Highlander ;D)

Maintenant alimentation par USB + Alimenation externe pour le 5v masse commune même programme.
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140401101644-tilowil-IMG-4148.JPG) (https://gamoovernet.pixhotel.fr/pics/20140401101644-tilowil-IMG-4148.JPG)
Voila mon casse tete. Dernière precision au cas ou pour mettre les masse en commun je prends une sortie GND de l'arduino (celle a coté de la sortie +5v) que je relie à la masse de mon alimentation de borne.

Ce matin je vais essayer par une alimentation de PC qui sera peut être plus stable.
[Edit]
Je viens de realiser l'essai en alimentant tout le monde par une seule alimentation de PC en utilisant le +5v 18A et le Gnd. J'alimente ma breadboard directement je me repique dessus pour alimenter l'Arduino par la pin +5v et la pin GND. l'arduino demarre mais l'affichage est toujours tout pourri

Vous allez me dire que c'est mon montage qui pue, mais non car j'ai utilisé l'exemple de la librairie Ledcontrol qui permet de cascader sur 8 matrices et la

au ralenti


A pleine vitesse. le rendu n'est pas le même qu'en vrai, surement du a la persistance rétinienne.
La différence entre mon programme et l'exemple c'est qu'avec l'exemple je n'allume que 1 led à la fois.


essai en alimentant le montage par l'alimentation PC (la matrice 1 et 3 reste éteinte alors qu'elles sont alumées si j'alimente par l'usb) une histoire de fou.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Mardi 01 Avril 2014, 14:16:41 PM
Donc en résumé :
Si tu allume très peu de LED ça marche.
Si tu en allume une dizaine par matrice ca marche plus.

Il faut que tu mettes à coté de chaque Max7221 un 10µF et un 100nF. C'est un régulateur PWM, il faut vraiment un découplage a coté de chaque circuit.

Si après, ça fonctionne toujours pas :
Qu'est ce qu'il se passe si tu mets RSET à 40KOhm ou plus?
Est ce que tu arrive à allumer toutes les LEDs d'une matrice?

Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: Tormak le Mardi 01 Avril 2014, 14:28:08 PM
Je vais peut-être me faire lyncher, mais chose toute bête, pourquoi n'utilise tout simplement pas une matrice plus grande ?
Comme celle-ci par exemple?
http://www.adafruit.com/products/420 (http://www.adafruit.com/products/420)
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Mardi 01 Avril 2014, 22:04:09 PM
Citation de: spectroman le Mardi 01 Avril 2014, 14:16:41 PM
Donc en résumé :
Si tu allume très peu de LED ça marche.
Si tu en allume une dizaine par matrice ca marche plus.

Il faut que tu mettes à coté de chaque Max7221 un 10µF et un 100nF. C'est un régulateur PWM, il faut vraiment un découplage a coté de chaque circuit.

Si après, ça fonctionne toujours pas :
Qu'est ce qu'il se passe si tu mets RSET à 40KOhm ou plus?
Est ce que tu arrive à allumer toutes les LEDs d'une matrice?


Merci beaucoup Spectroman. Tu viens de m'enlever une méga épine du pied. J'ai ajouté les 2 condensateurs a coté de chaque Max7221 et cela fonctionne. Ensuite j'ai remplacé les Max7221 par mes AS1107 et j'ai versé mon programme développé 100% théorique et j'ai quelques bugs. Cependant les 5 matrices sont capables d'être allumées. Ce qui est bien c'est que tout fonctionne avec une pile de 9V. Je vais posté une petite vidéo demain en essayant de ne pas dévoiler le déguisement final. Merci beaucoup Spectroman.

Citation de: Tormak le Mardi 01 Avril 2014, 14:28:08 PM
Je vais peut-être me faire lyncher, mais chose toute bête, pourquoi n'utilise tout simplement pas une matrice plus grande ?
Comme celle-ci par exemple?
http://www.adafruit.com/products/420 (http://www.adafruit.com/products/420)
Merci Tormak pour ton aide, pourquoi te ferais tu lyncher ? Ton idée n'est pas mauvaise, mais ne correspond pas à mon besoin. Vu l'espace que j'ai je ne peux pas dépasser 8 leds (de 5mm) de haut. il faut que ce soit visible quand même :D. Je pense qu'avec l'avancement du projet tu comprendras cette contrainte :D. Qui plus est il s'agit d'un module monobloc. les modules dont je me sert ne sont que pour mes tests et mes corrections de bugs. A terme je vais utilisé la matrice de leds que j'ai fabriqué avec mon fiston (c'est son projet c'est normal qu'il y participe).
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: cedricbionic le Mardi 01 Avril 2014, 22:59:24 PM
Très très beau projet  :-* pour avoir pas vu mal de video sur youtube sur ce sujet, je peux te dire que j'en ai réver  :ang:, je suis fan et j'ai tout de suite compris ton déguisement  ;)

Je vais suivre ton post avec GRAND Intéret.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: Little_Rabbit le Mercredi 02 Avril 2014, 11:41:30 AM
Salut,

Citation de: cedricbionic le Mardi 01 Avril 2014, 22:59:24 PM
pour avoir pas vu mal de video sur youtube sur ce sujet, je peux te dire que j'en ai réver  :ang:, je suis fan

C'est vrai que certains on carrément du level quand tu vois ce à quoi ils parviennent !!

Bon, y en a d'autres qui en ont moins :D, comme ici (http://www.frenzcircle.com/video/displayvideo/xo6ojd_tuto-casque-daft-punk_creation)...
(bon j'avoue, je n'ai pas eu le courage d'aller jusqu'au bout, si ça se trouve c'est une blague ! ;) )

Bon courage à toi tilowil !  ^-

A+
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Mercredi 02 Avril 2014, 12:59:14 PM
CitationBon, y en a d'autres qui en ont moins Cheesy, comme ici...

no comment :D


Apparemment, vu le format de la matrice, tu fais celui de thomas.

j'adore cette vidéo de la construction d'une réplique du casque de guy man :



Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Mercredi 02 Avril 2014, 16:52:58 PM
Bravo messieurs vous avez découvert le projet de déguisement que mon fils me réclame depuis l'été 2013.

Oui c'est bien une réplique du casque de Thomas que je dois réaliser. La matrice de 320 leds est presque prête. Il faut que je coupe et perce la sous visière. Il faut ensuite que je prépare le support pour la première couche du casque et le début du sculptage de la partie visière.

La partie programmation et électronique me prends un peu la tête, mais ça va beaucoup mieux (merci spectroman), maintenant que les 5 matrices affichent ce que je leur demande. Le projet doit être livré pour halloween 2014. Le plus compliqué reste à venir. Mais l'affichage et les jeux de lumières vont être bon.

C'est vrai que certain projet font peine à voir, mais je ne juge pas, ils sont fait avec les moyens de la personne et ses connaissances. Je ne dirais pas que mon projet sera parfait, mais je vais essayé de faire au mieux :D

Merci de vos messages et de votre aide quand je cale.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Mercredi 02 Avril 2014, 21:47:03 PM
En bonus tu peux :
1) lui faire des touches capacitives pour choisir les animations de l'écran (Je peux t'envoyer un pcb de touches à découper).
2) lui faire un ampli audio avec une sortie PWM (j'ai déjà fait des ultrasons à 40KHz, super propre avec un atxmega)

a+
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: cedricbionic le Mercredi 02 Avril 2014, 21:49:39 PM
Spectro tu m'en fait un ?  :D
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tikibzh le Jeudi 03 Avril 2014, 07:04:03 AM
La vidéo de Spectroman, c'est celle de Volpin Props, il a aussi réalisé celui de Thomas:
http://www.volpinprops.com/daft-punk-helmet-thomas-final/

Il vend le casque brut, aisi que différents composants pour le terminer
http://www.volpinprops.com/shop/

Il en a fabriqué et terminé plusieurs, tous vendus, mais il ne le fait plus.

A noter que maintenant, les casques des Dafts ne sont plus lumineux, seules les couleurs changent suivant les époques et les événements, blancs par ex pour les grammys ;)

Et les gamers, allez vous balader sur la boutique, il réalise des armes de jeux vidéo fabuleuses ;)

Mais c'est grâce à ses casque de Daft qu'il s'est fait connaitre.

Il a aussi réalisé un cosplay de malade, regardez ici;)
http://www.volpinprops.com/big-daddy-bioshock-2/
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Jeudi 03 Avril 2014, 07:57:13 AM
Citation de: spectroman le Mercredi 02 Avril 2014, 12:59:14 PM
no comment :D


Apparemment, vu le format de la matrice, tu fais celui de thomas.

j'adore cette vidéo de la construction d'une réplique du casque de guy man :




Dans le même genre fait par Harrison, tu as aussi celui ci

Mes plans vienne de lui, mais je n'ai pas son talent ;) :D

Citation de: spectroman le Mercredi 02 Avril 2014, 21:47:03 PM
En bonus tu peux :
1) lui faire des touches capacitives pour choisir les animations de l'écran (Je peux t'envoyer un pcb de touches à découper).
2) lui faire un ampli audio avec une sortie PWM (j'ai déjà fait des ultrasons à 40KHz, super propre avec un atxmega)

a+
J'avais pensé à un truc comme tes touches, mais je vais lui fabriquer les gants aussi, donc je ne sais pas si avec des sous gants de motards cela fonctionnera. Je vous ai fait la vidéo car ma programmation est quasiment finie. il me reste un élément à corriger (j'ai mal anticipé) et une dernière animation à programmer. Actuellement toutes animations confondues sur le frontal uniquement je tourne sur une boucle de 10 minutes (je m'amuse comme un petit fou avec l'arduino et les AS1107).
Maintenant il faut que j'intègre aussi les 3 boutons (1 pour le mode séquentiel, 1 pour figer l'animation sur le précédent et 1 bouton pour figer l'animation sur le suivant)

Pour le son je voulais lui intégrer un changeur de voix. Mais peut être pas pour ce Halloween :D.

L'affichage est perfectible, mais pour un premier essai je suis content. Je sais maintenant que je vais pouvoir passer à la suite et utiliser un Max7221 sur 3 autres pins de l'arduino pour faire les jeux de lumière des oreilles et des cotés de la visière.

Allez la vidéo (elle dure 10 minutes) et j'ai écrit intentionnellement l'animation que je vais jouer.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Jeudi 03 Avril 2014, 08:31:28 AM
super, ça prend forme.

c'est quoi le bug que l'on voit sur les colonnes 1 & 5 de la deuxième matrice?

c'est un problème de câblage?
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: Little_Rabbit le Jeudi 03 Avril 2014, 09:50:59 AM
Salut,

Citation de: tilowil le Jeudi 03 Avril 2014, 07:57:13 AM
Allez la vidéo (elle dure 10 minutes) et j'ai écrit intentionnellement l'animation que je vais jouer.

Et bien, pour quelqu'un qui débuterait en programmation d'arduino, tu te débrouilles comme un chef !!  ^-

Quelques petites remarques perso :
- je jouerais toutes les animations 2 fois plus vite, ce serait plus dynamique je trouve
- pour le mode Cylon, je ferais l'oeil un peu plus épais et plus large :) (éventuellement, en réduisant la largeur quand l'oiel arrive aux extrémités droite et gauche - je ne sais pas si je sui très clair ! :) )
- le mode SD est superbe, j'adore !
- pour le mode equalizer, j'aurais plus vu des barres qui ne bougent pas sur l'axe des X, qui partent du bas et montent à des hauteurs variables en se raccourcissant avec un amorti, un peu comme l'equalizer de Winamp :) (bon OK, plus facile à dire qu'à faire ! ;))

Mais bon, chapeau encore une fois  ^- !

A+
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Jeudi 03 Avril 2014, 10:34:39 AM
Citation de: spectroman le Jeudi 03 Avril 2014, 08:31:28 AM
super, ça prend forme.

c'est quoi le bug que l'on voit sur les colonnes 1 & 5 de la deuxième matrice?

c'est un problème de câblage?
Merci,

Oui c'est apparu quand j'ai échangé mes boitiers (remplacer les Max7221 par les AS1107). J'ai peut être un boitier défectueux. Je dois faire l'échange avec un autre (en premier permuter le 1 et le 2 pour voir si le défaut se déplace) et si l'échange ne suffit pas, procéder à un remplacement.

Citation de: Little_Rabbit le Jeudi 03 Avril 2014, 09:50:59 AM
Salut,

Et bien, pour quelqu'un qui débuterait en programmation d'arduino, tu te débrouilles comme un chef !!  ^-

[...]

Mais bon, chapeau encore une fois  ^- !

A+
Merci Little mais tu vas me faire rougir. L'arduino c'est de la programmation C like, ça va je connais, il a juste fallu apprendre les adressages des sorties. c'est un joujou fort intéressant d'ailleurs.

Concernant tes remarques :
Citation de: Little_Rabbit le Jeudi 03 Avril 2014, 09:50:59 AM
- je jouerais toutes les animations 2 fois plus vite, ce serait plus dynamique je trouve
la vitesse dépend du nombre de modules que je met en oeuvre, avec 3 modules c'est superbe, mais avec 5 j'ai ce ralentissement. Il faut que je travaille pour accélérer l'affichage, mais je ne sais pas encore comment faire.

Citation de: Little_Rabbit le Jeudi 03 Avril 2014, 09:50:59 AM
- pour le mode Cylon, je ferais l'oeil un peu plus épais et plus large :) (éventuellement, en réduisant la largeur quand l'oiel arrive aux extrémités droite et gauche - je ne sais pas si je sui très clair ! :) )
Oui tu es clair :D. je me suis taté pour cette animation d'abord je voulais le faire de la hauteur de la matrice, mais quand j'ai re visionné une video des cylons je me suis dit qu'un carre de 2x2 devrait être suffisant. En plus le casque sera chromé ce qui est ressemblant aux Cylons  =:)).

Aprèsje veux bien essayer ton idée, mais j'ai peur que ce soit trop gros. Je le programme en animation Cylon2 et je te fais une petite video.

Citation de: Little_Rabbit le Jeudi 03 Avril 2014, 09:50:59 AM
- le mode SD est superbe, j'adore !
Merci  <:). Mais la aussi la multiplication des modules ma fait au début une animation pas terrible. J'ai du renforcé la génération des étoiles en mettant une génération aléatoire de 5 étoiles au lieu 1 comme j'avais prévu au début.

Citation de: Little_Rabbit le Jeudi 03 Avril 2014, 09:50:59 AM
- pour le mode equalizer, j'aurais plus vu des barres qui ne bougent pas sur l'axe des X, qui partent du bas et montent à des hauteurs variables en se raccourcissant avec un amorti, un peu comme l'equalizer de Winamp :) (bon OK, plus facile à dire qu'à faire ! ;))
Je dois corriger cette animation car il y a un bug. Effectivement ce que j'avais prévu les barres reposent sur l'axe des X et montent et descendent suivant des valeurs tirées aléatoirement. Il n'y aura que 5 barres (1 par matrice).
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Samedi 05 Avril 2014, 13:39:52 PM
Petite avancée ce matin.
Le parasitage que j'avais sur la seconde matrice venais du boitier AS1107, je l'ai mis en premier et le parasite s'est déplacé sur la première matrice. Donc j'ai changé le boitier (j'en avais commandé 10 pour une utilisation de 5, mais j'ai d'autres projets pour les restants) et maintenant l'affichage est nickel.

Pour faire plaisir au petit lapin j'ai créée Cylon2


j'en ai profité pour corriger le vu metre (toujours pour faire plaisir au petit lapin)


ensuite pour vous faire comprendre la problématique de vitesse voici 2 essais
En utilisation 3 modules


en utilisation 5 modules (utilisation normale pour mon besoin)


donc pour essayer d'aller plus vite j'ai mis un step de 2 (mais c'est moche)


pour finir pour ceux qui voudrait une base de depart je vous laisse le code de ma programmation

AS1107.CPP

/*
  AS1107.cpp
*/
#include <avr/pgmspace.h>
#include "Arduino.h"
#include "AS1107.h"

const byte AS1107::_repcharoff  = 27;

// Font Data
PROGMEM prog_uchar _font[] = {
    // -------- Space
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    // -------- A
    0b01111110,
    0b10010000,
    0b10010000,
    0b01111110,
    // -------- B
    0b01101100,
    0b10010010,
    0b10010010,
    0b11111110,
    // -------- C
    0b10000010,
    0b10000010,
    0b01111100,
    // -------- D
    0b00111000,
    0b01000100,
    0b10000010,
    0b11111110,    
    // -------- E
    0b10000010,    
    0b10010010,    
    0b11111110,
    // -------- F
    0b10000000,        
    0b10010000,        
    0b11111110,
    // -------- G
    0b01011100,      
    0b10010010,
    0b10000010,
    0b01111100,
    // -------- H
    0b11111110,
    0b00010000,
    0b00010000,
    0b11111110,    
    // -------- I
    0b10000010,    
    0b11111110,    
    0b10000010,    
    // -------- J
    0b11111100,    
    0b00000010,
    0b00001100,
    // -------- K
    0b10000110,    
    0b01001000,    
    0b00110000,
    0b11111110,
    // -------- L
    0b00000010,      
    0b00000010,      
    0b11111110,
    // -------- M
    0b11111110,
    0b01100000,
    0b00111100,      
    0b01100000,      
    0b11111110,
    // -------- N
    0b11111110,
    0b00011000,
    0b01100000,      
    0b11111110,    
    // -------- O
    0b01111100,
    0b10000010,
    0b10000010,
    0b01111100,      
    // -------- P
    0b01100000,    
    0b10010000,
    0b10010000,
    0b11111110,
    // -------- Q
    0b01111010,
    0b10000100,
    0b10001010,
    0b01111100,    
    // -------- R
    0b01100110,      
    0b10011000,
    0b10010000,
    0b11111110,
    // -------- S
    0b10001100,
    0b10010010,
    0b01100010,    
    // -------- T
    0b10000000,      
    0b11111110,
    0b10000000,      
    // -------- U
    0b11111100,
    0b00000010,
    0b00000010,
    0b11111100,      
    // -------- V
    0b11000000,
    0b00111000,
    0b00000110,
    0b00111000,
    0b11000000,      
    // -------- W
    0b11111110,
    0b00001100,
    0b00111000,      
    0b00001100,      
    0b11111110,    
    // -------- X
    0b11000110,
    0b00111000,
    0b00111000,    
    0b11000110,
    // -------- Y
    0b11100000,
    0b00011110,
    0b11100000,    
    // -------- Z
    0b11000010,
    0b10110010,
    0b10001110,      
    // -------- Unknown character (#255)
    0b00111000,      
    0b00111000,
    0b00111000,
    // -------- 0
    0b01111100,
    0b10100010,
    0b10010010,
    0b01111100,      
    // -------- 1
    0b11111110,
    0b01000000,
    // -------- 2
    0b01100010,
    0b10010010,
    0b10001110,      
    // -------- 3
    0b01101100,
    0b10010010,
    0b10000010,      
    // -------- 4
    0b11111110,
    0b00010000,
    0b11110000,      
    // -------- 5
    0b10001100,
    0b10010010,
    0b11110010,      
    // -------- 6
    0b01001100,
    0b10010010,
    0b10010010,
    0b01111100,      
    // -------- 7
    0b11100000,
    0b10011110,
    0b10000000,      
    // -------- 8
    0b01101100,
    0b10010010,
    0b10010010,
    0b01101100,      
    // -------- 9
    0b01111100,
    0b10010010,
    0b10010010,
    0b01100100,      
    // -------- :
    0b00100100,
    // -------- ;
    0b00100110,
    0b00000001,
    // -------- !
    0b01100000,
    0b11111010,
    0b01100000,
    // -------- Heart (#)
    0b01111000,
    0b11111100,
    0b11111110,
    0b01111111,
    0b11111110,
    0b11111100,
    0b01111000,
    // -------- <
    0b01000100,
    0b00101000,
    0b00010000,
    // -------- =
    0b00101000,
    0b00101000,
    0b00101000,
    0b00101000,
    // -------- >
    0b00010000,
    0b00101000,
    0b01000100,
    // -------- ?
    0b01100000,
    0b10011010,
    0b10000000,
    // -------- @
    0b01111100,
    0b10000010,
    0b10111010,
    0b10100010,
    0b01011100,
    // -------- (
    0b10000010,
    0b01111100,
    // -------- )
    0b01111100,
    0b10000010,
    // -------- *
    0b00101000,
    0b00010000,
    0b00101000,
    // -------- +
    0b00010000,
    0b00010000,
    0b01111100,
    0b00010000,
    0b00010000,
    // -------- ,
    0b00000110,
    0b00000001,  
    // -------- -
    0b00010000,
    0b00010000,
    0b00010000,
    0b00010000,
    // -------- .
    0b00000010,
    // -------- /
    0b11000000,
    0b00111000,
    0b00000110,
    // -------- a
    0b00111110,
    0b00100010,
    0b00100010,
    0b00011100,
    // -------- b
    0b00011100,
    0b00100010,
    0b00100010,
    0b11111110,
    // -------- c
    0b00100010,
    0b00100010,
    0b00011100,
    // -------- d
    0b11111110,
    0b00100010,
    0b00100010,
    0b00011100,
    // -------- e
    0b00011000,
    0b00101010,
    0b00101010,
    0b00011100,
    // -------- f
    0b10010000,
    0b01111110,
    0b00010000,
    // -------- g
    0b00111110,
    0b00100101,
    0b00100101,
    0b00011000,
    // -------- h
    0b00011110,
    0b00100000,
    0b00100000,
    0b11111110,
    // -------- i
    0b00000010,
    0b01011110,
    0b00010010,
    // -------- j
    0b01011110,
    0b00000001,
    0b00000001,
    // -------- k
    0b00100010,
    0b00010100,
    0b00001000,
    0b11111110,
    // -------- l
    0b00000010,
    0b11111100,
    // -------- m
    0b00011110,
    0b00100000,
    0b00111110,
    0b00100000,
    0b00111110,
    // -------- n
    0b00011110,
    0b00100000,
    0b00100000,
    0b00111110,
    // -------- o
    0b00011100,
    0b00100010,
    0b00100010,
    0b00011100,
    // -------- p
    0b00001100,
    0b00010010,
    0b00010010,
    0b00011111,
    // -------- q
    0b00011111,
    0b00010010,
    0b00010010,
    0b00001100,
    // -------- r
    0b00010000,
    0b00100000,
    0b00111110,
    // -------- s
    0b00100100,
    0b00101010,
    0b00101010,
    0b00010010,
    // -------- t
    0b00100010,
    0b11111100,
    0b00100000,
    // -------- u
    0b00111110,
    0b00000010,
    0b00000010,
    0b00111100,
    // -------- v
    0b00111000,
    0b00000110,
    0b00111000,
    // -------- w
    0b00111110,
    0b00000010,
    0b00011110,
    0b00000010,
    0b00111100,
    // -------- x
    0b00110110,
    0b00001000,
    0b00110110,
    // -------- y
    0b00111110,
    0b00000101,
    0b00000101,
    0b00111001,
    // -------- z
    0b00110010,
    0b00101010,
    0b00100110,
    0b00100010,
    // -------- Empty Heart ($)
    0b01111000,
    0b10000100,
    0b10000010,
    0b01000001,
    0b10000010,
    0b10000100,
    0b01111000,
    // -------- Mickey Head (%)
    0b01101100,
    0b01110110,
    0b00011110,
    0b00011110,
    0b01110110,
    0b01101100,
    0b00000000,
    // -------- Skull (&)
    0b01111000,
    0b11011110,
    0b11011100,
    0b11110110,
    0b11011100,
    0b11011110,
    0b01111000,
    // -------- Eye(])
    0b00010000,
    0b00111000,
    0b01111100,
    0b00000110,
    0b00011010,
    0b00011010,
    0b00000110,
    0b01111100,
    0b00111000,
    0b00010000,
    // ---------- Eye([)
    0b00010000,
    0b00111000,
    0b00111100,
    0b00100100,
    0b00011000,
    0b00011000,
    0b00100100,
    0b00111100,
    0b00111000,
    0b00010000    
};


// Char width table
PROGMEM prog_uchar _charwidth[] = {4,4,4,3,4,3,3,4,4,3,3,4,3,5,4,4,4,4,4,3,3,4,5,5,4,3,3,
                                   3,4,2,3,3,3,3,4,3,4,4,1,2,3,7,3,4,3,3,5,2,2,3,5,2,4,1,
                                   3,4,4,3,4,4,3,4,4,3,3,4,2,5,4,4,4,4,3,4,3,4,3,5,3,4,4,
                                   7,7,7,10,10,0 };

// ASCII Codes of the implemented characters                                    
PROGMEM prog_uchar _charcodes[] = {32,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
                                   81,82,83,84,85,86,87,88,89,90,255,48,49,50,51,52,53,
                                   54,55,56,57,58,59,33,35,60,61,62,63,64,40,41,42,43,44,
                                   45,46,47,97,98,99,100,101,102,103,104,105,106,107,108,
                                   109,110,111,112,113,114,115,116,117,118,119,120,121,
                                   122,36,37,38,93,91,0};
// ------------------------------------------------------------------------------------
// Constructor, initialize arduino
AS1107::AS1107(byte cspin, byte clkpin, byte datapin)
{
  _cspin = cspin;
  _clkpin = clkpin;
  _datapin = datapin;
  pinMode(cspin, OUTPUT);
  pinMode(clkpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  digitalWrite(cspin,HIGH);
  digitalWrite(clkpin,LOW);
  digitalWrite(datapin,LOW);
}

// ------------------------------------------------------------------------------------
// Initializes Arduino and AS1107
// buffer is the initial screen buffer
void AS1107::Init(byte * buffer)
{
  _buffer = buffer;
  CalculateCharOffsets();
  // Clear Screen buffer
  Clear();
  for (int i=0; i<=HighestCtrlNum; i++) {
    WriteRegister(i, Registers::Shutdown, ShutdownModes::Normal);
    WriteRegister(i, Registers::DecodeMode, 0x00);
    WriteRegister(i, Registers::IntensityControl, 0x00);
    WriteRegister(i, Registers::ScanLimit, 0x07);
  }
}

// ------------------------------------------------------------------------------------
// Set the Screen buffer
void AS1107::SetBuffer(byte * buffer)
{
  _buffer = buffer;
}

// ------------------------------------------------------------------------------------
// 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 <= 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);
  }
}

// ------------------------------------------------------------------------------------
// Writes a column of data to the LED-Matrix
// column: column number, starting at 0
// data  : screen data to be written
void AS1107::WriteColumn( byte column,  byte data)
{
  // if you use unusual matrix row wiring, you can manipulate data here
  byte chip = (column) >>3;
  byte reg = (column % 8) +1;
  WriteRegister(chip, reg, data);
}

// ------------------------------------------------------------------------------------
// Sets the status of a LED in the screen buffer
void AS1107::SetLed(int x, int y, byte value)
{
  if (x<=Maxx && y<=Maxy && x>=0 && y>=0) {
    if (value>0) value = 1;
    SetLedInternal(x, y, value);
 }
}
void AS1107::SetLedD(int x, int y, byte value)
{
  if (x<=Maxx && y<=Maxy && x>=0 && y>=0) {
    if (value>0) value = 1;
    SetLedInternalD(x, y, value);
 }
}

// ------------------------------------------------------------------------------------
// Writes Buffer to Screen
// needs to be called after a graphics operation to see anything
void AS1107::Update()
{
  for (byte i=0; i<=Maxx; i++) {
    WriteColumn(i, _buffer[i]);
  }
}

// ------------------------------------------------------------------------------------
// Clear the Screen Buffer
void AS1107::Clear()
{
  for (byte i=0; i<=Maxx; _buffer[i++]=0);
}

// ------------------------------------------------------------------------------------
// Shift the content of the Screen buffer to the left
void AS1107::ShiftLeft()
{
  for (byte i=1; i<=Maxx; i++) {
    _buffer[i-1] = _buffer[i];
  }
  _buffer[Maxx] = 0;
}
// ------------------------------------------------------------------------------------
// Shift the content of the Screen buffer to the right
void AS1107::ShiftRight()
{
  for (byte i=Maxx; i>=1; i--) {
    _buffer[i] = _buffer[i-1];
  }
  _buffer[0] = 0;
}
// ------------------------------------------------------------------------------------
// Shift the content of the Screen buffer up
void AS1107::ShiftUp()
{
  for (byte i=0; i<=Maxx; i++) {
    _buffer[i] = _buffer[i]<<1 & 0xFE;
  }
}
// ------------------------------------------------------------------------------------
// Shift the content of the Screen buffer up
void AS1107::ShiftUp(byte from, byte to)
{
  for (byte i=from; i<=to; i++) {
    _buffer[i] = _buffer[i]<<1 & 0xFE;
  }
}
// ------------------------------------------------------------------------------------
// Shift the content of the Screen buffer down
void AS1107::ShiftDown()
{
  for (byte i=0; i<=Maxx; i++) {
    _buffer[i] = _buffer[i]>>1 & 0x7F;
  }
}
// ------------------------------------------------------------------------------------
// Shift the content of the Screen buffer down
void AS1107::ShiftDown(byte from, byte to)
{
  for (byte i=from; i<=to; i++) {
    _buffer[i] = _buffer[i]>>1 & 0x7F;
  }
}
// ------------------------------------------------------------------------------------
// draws a line from x0 ,y0 to x1,y1
void AS1107::DrawLine(int x0, int y0, int x1, int y1)
{

  int dx =  abs(x1-x0), sx = x0<x1 ? 1 : -1;
  int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
  int err = dx+dy, e2; /* error value e_xy */

  for(;;){  /* loop */
    SetLed(x0,y0,ON);
    if (x0==x1 && y0==y1) break;
    e2 = 2*err;
    if (e2 >= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
    if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
  }
}
// ------------------------------------------------------------------------------------
// erase a line from x0 ,y0 to x1,y1
void AS1107::EraseLine(int x0, int y0, int x1, int y1)
{

  int dx =  abs(x1-x0), sx = x0<x1 ? 1 : -1;
  int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
  int err = dx+dy, e2; /* error value e_xy */

  for(;;){  /* loop */
    SetLedD(x0,y0,OFF);
    if (x0==x1 && y0==y1) break;
    e2 = 2*err;
    if (e2 >= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
    if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
  }
}
// ------------------------------------------------------------------------------------
// draws a box from x0,x0 to x1,y1
void AS1107::DrawBox(int x0, int y0, int x1, int y1)
{
  DrawLine(x0,y0,x1,y0);
  DrawLine(x1,y0,x1,y1);
  DrawLine(x1,y1,x0,y1);
  DrawLine(x0,y1,x0,y0);
}
// ------------------------------------------------------------------------------------
// draws an ellipse
// center xm, ym   - radius a,b
void AS1107::DrawEllipse(int xm, int ym, int a, int b)
{
   if (a ==0 && b== 0) {
  SetLed(xm,ym,ON);
  return;
   }

   int dx = 0, dy = b; /* first quadrant from top left to bottom right */
   int a2 = a*a, b2 = b*b;
   int err = b2-(2*b-1)*a2, e2; /* error value in the first step */

   do {
     SetLed(xm+dx, ym+dy, ON); /* I. Quadrant */
     SetLed(xm-dx, ym+dy, ON); /* II. Quadrant */
     SetLed(xm-dx, ym-dy, ON); /* III. Quadrant */
     SetLed(xm+dx, ym-dy, ON); /* IV. Quadrant */

     e2 = 2*err;
     if (e2 <  (2*dx+1)*b2) { dx++; err += (2*dx+1)*b2; }
     if (e2 > -(2*dy-1)*a2) { dy--; err -= (2*dy-1)*a2; }
   } while (dy >= 0);

   while (dx++ < a) { /* correction for flat ellipses (b=1) */
     SetLed(xm+dx, ym, ON);
     SetLed(xm-dx, ym, ON);
   }
}

// ------------------------------------------------------------------------------------
// Writes Text at a screen position
void AS1107::DrawText (int x, int y, char *str)
{
  byte count;
  char thechar;
  while (*str != '\0') {
    x+=DrawChar(x, y, *str);
    str++;
  }
}

// ------------------------------------------------------------------------------------
// Draws a single character at a screen position
// returns the x-position for the next character
byte AS1107::DrawChar (int x, int y, char thechar)
{
  y+=7;
  byte charnum, colct, count=0, colbits;
  int fontidx;
  charnum = GetInternalCharCode(thechar);

  // get the location of the first column of the font
  fontidx = _charoffset[charnum]-1;

  // get the width of the font
  colct = pgm_read_byte_near(_charwidth + charnum);
  for (byte i=colct; i>0; i--) {
    colbits = pgm_read_byte_near(_font + fontidx + i);
    for (byte j=0; j<=7; j++) {
      if ((colbits >>j) & 1) {
        SetLed(x, y-j, 1);
      }
    }
    x++;
  }
  return colct+1;
}
// ------------------------------------------------------------------------------------
// Sets the Text for Scrolline
void AS1107::SetScrollText(char *string, int charspacing)
{
  _charspacing = charspacing;
  _outputstring = string;
  _curchr = string;
  _hastext = true;
  _colct =-1;
}

// ------------------------------------------------------------------------------------
// Scrolls the text one pixel to the left
// returns true if last character has been displayed
boolean AS1107::TextScroll()
{
  boolean lastchar = false;
  byte colbits = 0;
    if (_colct == (0-_charspacing-1)) {
      lastchar = NextCharacter();
    }
    if (_colct>=0) {
      colbits = pgm_read_byte_near(_font + _fontidx + _colct);
    }
    ShiftLeft();
    _buffer[Maxx] = colbits;
    Update();
    _colct--;
  return lastchar;
}

// ------------------------------------------------------------------------------------
// PRIVATE (Internal) functions
// ------------------------------------------------------------------------------------
// Set LED without Parameter check
void AS1107::SetLedInternal(byte x, byte y, byte value)
{
  _buffer[x] |= (value << (Maxy-y));
}
// Set LED without Parameter check
void AS1107::SetLedInternalD(byte x, byte y, byte value)
{
  _buffer[x] = (value << (Maxy-y));
}

// ------------------------------------------------------------------------------------
// fetches the next character of the Scrollline
// returns true if string is at the end
boolean AS1107::NextCharacter()
{
  boolean lastchar = false;
  if (_hastext) {
    char thechar = *_curchr;
    boolean found = false;
    byte charnum = 0;
    byte i;
    // if the string ends, start from the beginning
    if (thechar == 0) {
      lastchar = true;
      _curchr = _outputstring;
      thechar = *_curchr;
    }

    charnum = GetInternalCharCode(thechar);

    // get the offset of the first column of the character
    _fontidx = _charoffset[charnum];

    // get the width of the font
    _colct = pgm_read_byte_near(_charwidth + charnum) -1;
  }
  else {
    _fontidx= _charoffset[_repcharoff];
    _colct = pgm_read_byte_near(_charwidth + _repcharoff);
  }
  *_curchr++;
  return lastchar;
}
// ------------------------------------------------------------------------------------
// calculates Character offsets from font width table in EEPROM
void AS1107::CalculateCharOffsets()
{
  int off =0;
  int idx=0;
  int w=0;
  int i=0;

  do {
    _charoffset[i]=off;
    w = pgm_read_byte_near(_charwidth+i);
    off += w;
    i++;
  } while (w != 0);
}

// ------------------------------------------------------------------------------------
// gets the character number of the built-in-font from the ASCII table
// returns number of the replacement character for unknown characters
byte AS1107::GetInternalCharCode(byte thechar)
{
    int i=0;
    int charnum;
    do {
      charnum = pgm_read_byte_near(_charcodes + i);
      if (charnum == thechar) break;
      i++;
    } while (charnum != 0 );
    if (charnum == 0) i = _repcharoff;
    return i;
}

Il s'agit de la librairie de Stephan Elsner que j'ai remanié pour mes besoins.

AS1107.h

/*
  AS1107.h
*/

#ifndef AS1107_h
#define AS1107_h

#include "Arduino.h"
#include <avr/pgmspace.h>

#define ON 1
#define OFF 0


// --------------------------------------------------------------------------------------------------------------------------
class AS1107
{
  public:
    AS1107(byte cspin, byte clkpin, byte datapin);
    void WriteRegister2(byte chip, byte reg, byte data);
    void WriteRegister(byte chip, byte reg, byte data);
    void WriteColumn( byte column, byte data);
    void Init(byte *buffer);
    void SetBuffer(byte *buffer);
    void SetLed(int x, int y, byte value);
    void SetLedD(int x, int y, byte value);
    void Clear();
    void Update();
    void ShiftLeft();
    void ShiftRight();
    void ShiftUp();
    void ShiftDown();
    void ShiftUp(byte from, byte to);
    void ShiftDown(byte from, byte to);
    void DrawLine(int x0, int y0, int x1, int y1);
    void EraseLine(int x0, int y0, int x1, int y1);
    void DrawBox(int x0, int y0, int x1, int y1);
    void DrawEllipse(int xm, int ym, int a, int b);
    void SetScrollText(char *string, int charspacing);
    void DrawText (int x, int y, char *str);
    byte DrawChar (int x, int y, char thechar);

    boolean TextScroll();

    // ***************************************
    // Set your module configuration here
    // ***************************************
    static const byte NbMod=5;
    static const byte Maxx=(8*NbMod)-1;      // maximum x - Pixels of the Module
    static const byte Maxy=7;         // maximum y - Pixels of the Module
    static const byte HighestCtrlNum=NbMod-1; // Number of Matrix modules -1 (0 = single module)

  private:
    byte _cspin;
    byte _clkpin;
    byte _datapin;
    byte *_buffer;                    // pointer to current screen buffer

    static const byte _repcharoff;    // Offset of the replacement for unknown characers
    int  _charoffset[87];             // Start position in Array
    char *_outputstring;              // pointer to start of output string
    char *_curchr;                    // pointer to current char of output String
    int _fontidx;                     // current byte in font to display
    int _colct;                       // to count the columns of character to display
    byte _charspacing;                // the coulumns of space between characters
    boolean _hastext;

    void SetLedInternal(byte x, byte y, byte value);
    void SetLedInternalD(byte x, byte y, byte value);
    boolean NextCharacter();
    void CalculateCharOffsets();
    byte GetInternalCharCode(byte thechar);
};

// --------------------------------------------------------------------------------------------------------------------------
// AS1107-Register
class Registers
{
  public:
    static const byte NoOp   = 0x00;
    static const byte Digit0 = 0x01;
    static const byte Digit1 = 0x02;
    static const byte Digit2 = 0x03;
    static const byte Digit3 = 0x04;
    static const byte Digit4 = 0x05;
    static const byte Digit5 = 0x06;
    static const byte Digit6 = 0x07;
    static const byte Digit7 = 0x08;
    static const byte DecodeMode = 0x09;
    static const byte IntensityControl = 0x0A;
    static const byte ScanLimit = 0x0B;
    static const byte Shutdown = 0x0C;
    static const byte Feature = 0x0E;
    static const byte DisplayTest = 0x0F;
};

// --------------------------------------------------------------------------------------------------------------------------
// Values to write to the Shutdown Register
class ShutdownModes
{
  public:
    static const byte ShutdownResetFeature = 0x00;  // Shutdown Mode, Reset Feature Register to Default Settings
    static const byte Shutdown             = 0x80;  // Shutdown Mode, leaving Feature Register unchanged
    static const byte NormalResetFeature   = 0x01;  // Normal Mode, Reset Feature
    static const byte Normal               = 0x81;  // Normal Mode, Feature unchanged
};

// Bits in the feature-Register, desired Settings must be OR'ed together
class Features
{
  public:
    static const byte ExternalClock        = 0x01;  // ExternalClock active
    static const byte ResetRegisters       = 0x02;  // Resets all control registers except the Feature Register.
    static const byte HexDecoding          = 0x04;  // 1 = Enable HEX decoding, 0 = Enable Code-B decoding
    static const byte SPIEnable            = 0x08;  // Enables the SPI-compatible interface.(AS1106 only).
    static const byte BlinkEnable          = 0x10;  // Enables blinking.
    static const byte BlinkSlow            = 0x20;  // Sets blink with low frequency
                                                    // (with the internal oscillator enabled)

    static const byte BlinkSync            = 0x40;  // Synchronizes blinking on the rising edge of pin LOAD/CSN.
                                                    // The multiplex and blink timing counter is cleared on the
                                                    // rising edge of pin LOAD/CSN. By setting this bit in
                                                    // multiple AS1106/AS1107 devices, the blink timing can
                                                    // be synchronized across all the devices.

    static const byte BlinkStartWithOn     = 0x80;  // Start Blinking with display enabled phase.
                                                    // When bit D4 (blink_en) is set, bit D7
                                                    // determines how blinking starts.
                                                    // 0 = Blinking starts with the display turned off.
                                                    // 1 = Blinking starts with the display turned on.
};

#endif


Avec mon code je dois dépasser la capacité de l'éditeur, la suite dans le message suivant.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Samedi 05 Avril 2014, 14:00:58 PM
La suite...
et enfin le programme servant pour l'affichage
CTB.ino

#include <AS1107.h>

// Arduino pins
const byte CsnPin = 10;    // Chip select
const byte ClkPin = 11;    // Serial Clock
const byte DataPin = 12;   // Serial Data

byte buffer[40];          // Screen buffer (Nb. de modules * 8)
AS1107 matrix(CsnPin, ClkPin, DataPin);

const byte d = 0;
int count=1;
void setup()
{
  //Serial.begin(9600);
  matrix.Init(buffer);
  matrix.SetScrollText("% Halloween Party 2014.  &    ", 1);
}

void loop()
{
   // Animations programmées (20)
   // - Scroll "[Mickey] Halloween Party 2014. [Skull]"
   // - Pulsation de cercles (CirclePulsate())
   // - Chute d'étoiles (StarsDown())
   // - Ligne tournante (Rotator1())
   // - Champ d'étoiles (StarsRight())
   // - Lignes (Lines())
   // - Balle rebondissante (bounce())
   // - Oeil avec clignement (EyeBlink())
   // - Pulsation cardiaque (HeartPulsing())
   // - Coeurs (plein/vide) (Hearts())
   // - Gros "OK" (BigOk())
   // - Viseur Cyclope (Cyclope())
   // - Cylon (oeil 4 leds) (Cylon())
   // - Cylon2 (oeil 16 leds) (Cylon2())
   // - Lignes verticales scrollent vers la gauche (VertiLines("L"))
   // - Lignes verticales scrollent vers la droite (VertiLines("R"))
   // - Remplissage vers la droite et retour (FillingLine("R"))
   // - Remplissage vers la gauche et retour (FillingLine("L"))
   // - Faux vu-metre sur 5 colonnes (sep : 1 led) (Egaliser())
   // - Remplissage bloc (FillingBlock())
   
   if (matrix.TextScroll())
   {
     delay(2000);
     for (int i=0; i<=7; i++)
     {
       matrix.ShiftUp();
       delay(50);
       matrix.Update();
     }
 
   matrix.Clear();
   matrix.DrawText(0,0,"EyeBlink");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   EyeBlink(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"HP");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   HeartPulsing(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"Lines");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   Lines(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"Hearts");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   Hearts(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"BOK");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   BigOk(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"Cyclops");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   Cyclope(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"Cylon");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   Cylon(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"Cylon2");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   Cylon2(); // V

   matrix.Clear();
   matrix.DrawText(0,0,"VertiL");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   VertiLines("L"); // V

   matrix.Clear();
   matrix.DrawText(0,0,"VertiR");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   VertiLines("R"); // V

   matrix.Clear();
   matrix.DrawText(0,0,"FillL");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   FillingLine("L"); // V

   matrix.Clear();
   matrix.DrawText(0,0,"FillR");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   FillingLine("R"); // \ depilement à revoir.

   matrix.Clear();
   matrix.DrawText(0,0,"EQ");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   Egaliser(); // V
   
   matrix.Clear();
   matrix.DrawText(0,0,"FB");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   FillingBlock(); //

   matrix.Clear();
   matrix.DrawText(0,0,"Circle");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   
   // \WRO   
   for (int i=0; i<=10; i++)
   {
     CirclePulsate();
   }
   matrix.Clear();
   matrix.DrawText(0,0,"SD");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   
   StarsDown();
   matrix.Clear();
   matrix.DrawText(0,0,"Rotate");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   
   for (int i=0; i<=5; i++)
   {
     Rotator1();
   }
   matrix.Clear();
   matrix.DrawText(0,0,"SR");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   
   StarsRight();
   
   for (int i=0; i<=AS1107::Maxx; i++)
   {
     matrix.ShiftRight();
     delay(5);
     matrix.Update();
   }
   matrix.Clear();
   matrix.DrawText(0,0,"bounce");
   matrix.Update();
   delay(2000);
   matrix.Clear();
   
   for (int i=1; i<=3; i++)
   {
     bounce();
//  }}}}
}
}
   delay(10);
}

void FillingBlock()
{
  int dx=0;
  int fx=AS1107::Maxx-4;

  for (int i=0;i<=AS1107::Maxx/4;i++)
  {
   // Descente du bloc
   for (int j=0;j<=7;j++)
   {
    matrix.DrawLine(dx,j,dx,j+4);
    matrix.Update();
    delay(d);
   }
   if (fx!=dx)
   {
     // on pousse le bloc pour l'empiler
     for (int j=dx+1;j<=fx-4;j++)
     {
       matrix.DrawLine(j+4,0,j+4,7);
       matrix.EraseLine(j-1,0,j-1,7);
       matrix.Update();
       delay(d);
     }
     fx=fx-4;
   }
     
  } 
}

void DrawEgaliser(int colx[], int larg[], int coly[], int oldy[])
{
int realy[]={7,6,5,4,3,2,1,0};
matrix.Clear();
for (int i=0;i<=6;i++)
{
     for (int j=realy[0];j>=realy[coly[i]];j--)
     {
       matrix.DrawLine(colx[i],j,colx[i]+larg[i],j);
     } 
}
matrix.Update();


void Egaliser()
{
// definition des positions des colonnes
int colx[]= {0,4,10,16,22,28,34};
// definition des largeurs des colonnes
int larg[]= {2,4,4,4,4,4,4};
// definition des hauteurs des colonnes
int coly[]= {7,7,7,7,7,7,7};
// définition des variable de sauvegardes
int oldy[]={0,0,0,0,0,0,0};

matrix.Clear();
matrix.Update();
// dessin de la base de l'egaliseur
for (int j=0;j<=100;j++)
{
  //définition des nouvelles hauteurs
  for (int i=0;i<=6;i++)
  {
   coly[i]=random(0,8);
  }
  DrawEgaliser(colx,larg,coly,oldy);
  delay(100);
  for (int i=0;i<=6;i++)
  {
   oldy[i]=coly[i];
  }     
}


void FillingLine(char* sens)
{
  int dx=0;
  int fx=AS1107::Maxx;
  matrix.Clear();
  matrix.Update();
  if (sens=="R")
  {
   for (int i=0;i<=AS1107::Maxx;i++)
   {
     // dessin de la ligne a pousser
     matrix.DrawLine(dx,0,dx,7);
     matrix.Update();
     // on pousse la ligne pour l'empiler
     for (int j=1;j<=fx;j++)
     {
       matrix.DrawLine(j,0,j,7);
       matrix.EraseLine(j-1,0,j-1,7);
       matrix.Update();
       delay(d);
     }
     fx--; 
   }
   delay(1000);
   // on depile
   for (int i=0;i<=AS1107::Maxx;i++)
   {
     // on pousse la ligne pour la dépiler
     for (int j=fx;j>=0;j--)
     {
       matrix.DrawLine(j-1,0,j-1,7);
       matrix.EraseLine(j,0,j,7);
       matrix.Update();
       delay(d);
     }
     fx++; 
   }
}
else if (sens=="L")
{
   for (int i=0;i<=AS1107::Maxx;i++)
   {
     // dessin de la ligne a pousser
     matrix.DrawLine(fx,0,fx,7);
     matrix.Update();
     // on pousse la ligne pour l'empiler
     for (int j=fx;j>=dx;j--)
     {
       matrix.DrawLine(j,0,j,7);
       matrix.EraseLine(j+1,0,j+1,7);
       matrix.Update();
       delay(d);
     }
     dx++; 
   }
   delay(1000);
   // on depile
   for (int i=0;i<=AS1107::Maxx;i++)
   {
     // on pousse la ligne pour la dépiler
     for (int j=dx;j<=fx;j++)
     {
       matrix.DrawLine(j+1,0,j+1,7);
       matrix.EraseLine(j,0,j,7);
       matrix.Update();
       delay(d);
     }
     dx--; 
   }



void VertiLines(char* sens)
{
  int x=0;
  matrix.Clear();
  matrix.Update();
  if (sens == "L")
  {
   x=AS1107::Maxx;
  } 
  for (int j=0;j<=100;j++)
  {
    if ((j%8)==0)
    {
      matrix.DrawLine(x,0,x,7);
    }
    else
    {
      if (sens=="L")
      {
        matrix.ShiftLeft();
      }
      else
      {
        matrix.ShiftRight();
      }
    }
    matrix.Update();
    delay(d);
  }


void Cylon()
{
  matrix.Clear();
  matrix.Update();
  // Initialisation du carré (oeil)
  matrix.DrawBox(0,3,1,4);
  matrix.Update();
  // Lancement du scroll
  for (int j=1;j<=5;j++)
  {
    for (int i=0;i<=(AS1107::Maxx-2);i++)
    {
       matrix.ShiftRight();
       delay(5);
       matrix.Update();
    } 
    for (int i=0;i<=(AS1107::Maxx-2);i++)
    {
       matrix.ShiftLeft();
       delay(5);
       matrix.Update();
    } 
  } 

void Cylon2()
{
  matrix.Clear();
  matrix.Update();
  // Initialisation du carré (oeil)
  matrix.DrawBox(1,3,2,4);
  matrix.DrawBox(0,2,3,5);
  matrix.Update();
  // Lancement du scroll
  for (int j=1;j<=5;j++)
  {
    for (int i=0;i<=(AS1107::Maxx-4);i++)
    {
       matrix.ShiftRight();
       delay(5);
       matrix.Update();
    } 
    for (int i=0;i<=(AS1107::Maxx-4);i++)
    {
       matrix.ShiftLeft();
       delay(5);
       matrix.Update();
    } 
  } 


void Cyclope()
{
  int lx = 0;
  int ly = 0;
  int rx = AS1107::Maxx;
  int ry = AS1107::Maxy;
 
  matrix.Clear();
  matrix.Update();
  for (int j=1;j<=4;j++)
  {
    matrix.DrawBox(rx,ry,lx,ly);
    matrix.Update();
    delay(1000);
    lx++;
    rx--;
    for (int i=1;i<=4;i++)
    {
      matrix.DrawBox(rx,ry,lx,ly);
      lx++;
      rx--;
      matrix.Update();
    }
    ly++;
    ry--;
  }
}

void BigOk()
{
  int o = 17;
  int k = 22;
  matrix.Clear();
  for (int i=1; i<=9; i++)
  {
    if (i < 4)
    {
      matrix.DrawLine(o,0,o,7);
      matrix.DrawLine(k,0,k,7);
    }
    if (i > 3 and i < 7)
    {
      matrix.SetLed(o,0,ON);
      matrix.SetLed(o,7,ON);
      matrix.DrawLine(k,3-(i-4),k,4+(i-4));
    }
    if (i>6)
    {
      matrix.DrawLine(o,0,o,7);
      // Spécificité K
      if (i==7) matrix.DrawLine(k,0,k,7);
      if (i==8)
      {
        matrix.DrawLine(k,0,k,2);
        matrix.DrawLine(k,5,k,7);
      }
      if (i==9)
      {
        matrix.DrawLine(k,0,k,1);
        matrix.DrawLine(k,6,k,7);
      }
    }
    matrix.Update();
    o--;
    k++;
    delay(d);
  }
  delay(3000);
  for (int i=0; i<=5; i++)
  {
    matrix.Clear();
    matrix.Update();
    delay(500);
    // Ecriture du gros OK
    // O
    matrix.DrawBox(9,0,17,7);
    matrix.DrawBox(10,0,16,7);
    matrix.DrawBox(11,0,15,7);
    // K
    matrix.DrawLine(22,0,22,7);
    matrix.DrawLine(23,0,23,7);
    matrix.DrawLine(24,0,24,7);
    matrix.DrawLine(25,3,28,0);
    matrix.DrawLine(25,4,28,7);
    matrix.DrawLine(26,3,29,0);
    matrix.DrawLine(26,4,29,7);
    matrix.DrawLine(27,3,30,0);
    matrix.DrawLine(27,4,30,7);
    matrix.DrawLine(28,3,30,1);
    matrix.DrawLine(28,4,30,6);
    //
    matrix.Update();
    delay(500);
  }
  // Fermeture du OK
  for (int i=9; i>=0; i--)
  {
    if (i < 4)
    {
      matrix.EraseLine(o,0,o,7);
      matrix.EraseLine(k,0,k,7);
    }
    if (i > 3 and i < 7)
    {
      matrix.SetLedD(o,0,OFF);
      matrix.SetLedD(o,7,OFF);
      matrix.EraseLine(k,3-(i-4),k,4+(i-4));
    }
    if (i>6)
    {
      matrix.EraseLine(o,0,o,7);
      // Spécificité K
      if (i==7) matrix.EraseLine(k,0,k,7);
      if (i==8)
      {
        matrix.EraseLine(k,0,k,2);
        matrix.EraseLine(k,5,k,7);
      }
      if (i==9)
      {
        matrix.EraseLine(k,0,k,1);
        matrix.EraseLine(k,6,k,7);
      }
    }
    matrix.Update();
    o++;
    k--;
    delay(d);
  }


void Hearts()
{
  for (int i=0; i<=5; i++)
  {
    matrix.Clear();
    matrix.DrawText(4,0,"# # #");
    matrix.Update();
    delay(2000);
    matrix.Clear();
    matrix.DrawText(4,0,"$ $ $");
    matrix.Update();
    delay(2000);
  }


void HeartPulsing()
{
  // Allumage du Heart Pulse
  for( int i=0; i <= AS1107::Maxx; i++)
  {
    if (i < 14 or i > 24)
    {
      matrix.SetLed(i,3,ON);
    }
    if (i > 13 and i < 17)
    {
      matrix.SetLed(i,16-i,ON);
    } 
    if (i > 16 and i < 23)
    {
      matrix.SetLed(i,i-16,ON);
    } 
    if (i > 22 and i < 25)
    {
      matrix.SetLed(i,28-i,ON);
    } 
    matrix.Update();
    delay(d);
  }
  // Extinction du Heart Pulse
  for( int i=0; i <= AS1107::Maxx; i++)
  {
    if (i < 14 or i > 24)
    {
      matrix.SetLedD(i,3,OFF);
    }
    if (i > 13 and i < 17)
    {
      matrix.SetLedD(i,16-i,OFF);
    } 
    if (i > 16 and i < 23)
    {
      matrix.SetLedD(i,i-16,OFF);
    } 
    if (i > 22 and i < 25)
    {
      matrix.SetLedD(i,28-i,OFF);
    } 
    matrix.Update();
    delay(d);
  }
}

void EyeHeart()
{
  matrix.Clear();
  matrix.DrawText(8,0,"%");
  matrix.DrawText(24,0,"%");
  matrix.Update();
  delay(2000);
}

void Lines()
{
  for (int j=1; j<=5; j++)
  {
    for (int i=0; i<=3; i++)
    {
      matrix.Clear();
      matrix.DrawLine(0,0+i,AS1107::Maxx,0+i);
      matrix.DrawLine(0,AS1107::Maxy-i,AS1107::Maxx,AS1107::Maxy-i);
      matrix.Update();
      delay(500);
    }
    for (int i=3; i>=0; i--)
    {
      matrix.Clear();
      matrix.DrawLine(0,0+i,AS1107::Maxx,0+i);
      matrix.DrawLine(0,AS1107::Maxy-i,AS1107::Maxx,AS1107::Maxy-i);
      matrix.Update();
      delay(500);
    }
  }
}

void EyeBlink()
{
for (int i=0; i<=5; i++)
{
   matrix.Clear();
   // dessin des yeux
   matrix.DrawText(4,0,"]  ]");
   matrix.Update();
   delay(5000);
   matrix.Clear();
   matrix.DrawText(4,0,"[  [");
   matrix.Update();
   delay(500);
}
}
 
void CirclePulsate()
{
   for( int i=0; i<=15; i++)
   {
     matrix.Clear();
     matrix.DrawEllipse(AS1107::Maxx/2,4,i,i);
     matrix.Update();
     delay(d);
   }
}

void StarsDown()
{
     for( int i=0; i<=200; i++)
     {
       matrix.ShiftDown();
       matrix.SetLed((byte) random(0,AS1107::Maxx+1),0,1);
       matrix.SetLed((byte) random(0,AS1107::Maxx+1),0,1);
       matrix.SetLed((byte) random(0,AS1107::Maxx+1),0,1);
       matrix.SetLed((byte) random(0,AS1107::Maxx+1),0,1);
       matrix.SetLed((byte) random(0,AS1107::Maxx+1),0,1);
       matrix.Update();
       delay(d);
     }
}

void StarsRight()
{
     for( int i=0; i<=200; i++)
     {
       matrix.ShiftRight();
       matrix.SetLed(0,(byte) random(0,AS1107::Maxy+1),1);
       matrix.Update();
       delay(d);
     }
}

void Rotator1()
{
   for( int i=0; i<=AS1107::Maxx-1; i++)
   {
     matrix.Clear();
     matrix.DrawLine(i,0,AS1107::Maxx-i,AS1107::Maxy);
     matrix.Update();
     delay(d);
   }
   for( int i=0; i<=6; i++)
   {
     matrix.Clear();
     matrix.DrawLine(AS1107::Maxx,i,0,7-i);
     matrix.Update();
     delay(d);
   }
}

void bounce()
{
   int rad=0;
   float y=random(0,AS1107::Maxy+1);
   float x=random(0,AS1107::Maxx+1);
   float xacc=random(0,5)-2;
   float yacc=random(0,5)-2;
   float yg=0.08;
   if (xacc == 0) xacc = 1;
   if (yacc == 0) yacc = -1;
   
   for (int i=1; i<=300; i++)
   {
     x+=xacc;
     y+=yacc;
     yacc += yg;
     if (x >= (AS1107::Maxx-rad))
     {
       xacc = -xacc*0.9;
       x= AS1107::Maxx -rad;
     }
     else if (x <= rad)
     {
       xacc = -xacc*0.8;
       x= rad;
     }
     if (y >= (AS1107::Maxy-rad))
     {
       yacc = -(yacc*0.80);
       y= AS1107::Maxy -rad;
     }
     else if (y <= rad)
     {
       yacc = -yacc*0.8;
       y= rad;
     }
     matrix.Clear();
     matrix.SetLed(x,y,1);
     matrix.Update();
   }
}


Il me reste encore un peu de travail sr le code, entre autres augmenter sa vitesse (si vous avez des idées je suis preneur), programmer l'animation des oreilles et du coté de la visière (piloté par 1 seul AS1107). Il faut aussi que je programme les boutons (séquentiel, précédent, suivant).
Mon fils m'ayant demander un second scroll je me suis rendu compte d'un bug. Actuellement je ne peux mettre qu'un seul scroll. Un bug a corriger  :D.
Une fois tous ces éléments de programmations finis et verrouillé par des tests sur breadboard, je poursuivrais le reste du déguisement.

Merci pour vos messages, votre aide.
@ petit lapin : "Alors heureux ?"  :D :D :D
@ spectroman : Tu te rends compte que tous ça c'est grâce à toi :)
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Samedi 05 Avril 2014, 19:21:23 PM


const byte CsnPin = 10;    // Chip select
const byte ClkPin = 11;    // Serial Clock
const byte DataPin = 12;   // Serial Data

byte buffer[40];          // Screen buffer (Nb. de modules * 8)
AS1107 matrix(CsnPin, ClkPin, DataPin);

j'ai jamais fait de c++, mais je suis un gros radin avec la RAM.

const mets les données en zone Read only. Mais comme sur un atmega le cpu ne peut pas lire des données en flash (sauf avec des fonctions spéciales), const ne sert presque à rien, ça reste des données en RAM.

tu peux pas faire un define pour CsnPin....?


void Egaliser()
{
// definition des positions des colonnes
int colx[]= {0,4,10,16,22,28,34};
// definition des largeurs des colonnes
int larg[]= {2,4,4,4,4,4,4};
// definition des hauteurs des colonnes
int coly[]= {7,7,7,7,7,7,7};
// définition des variable de sauvegardes
int oldy[]={0,0,0,0,0,0,0};


64 octets sur la pile, assassin. >:D

Citation
Merci pour vos messages, votre aide.
@ petit lapin : "Alors heureux ?"  :D :D :D
@ spectroman : Tu te rends compte que tous ça c'est grâce à toi :)
non c'est toi qui a fait tout le boulot :D
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Samedi 05 Avril 2014, 20:15:22 PM
Je n'ai pas tout compris dans tes remarques, désolé. :(

Citation de: spectroman le Samedi 05 Avril 2014, 19:21:23 PM

const byte CsnPin = 10;    // Chip select
const byte ClkPin = 11;    // Serial Clock
const byte DataPin = 12;   // Serial Data

byte buffer[40];          // Screen buffer (Nb. de modules * 8)
AS1107 matrix(CsnPin, ClkPin, DataPin);

j'ai jamais fait de c++, mais je suis un gros radin avec la RAM.

const mets les données en zone Read only. Mais comme sur un atmega le cpu ne peut pas lire des données en flash (sauf avec des fonctions spéciales), const ne sert presque à rien, ça reste des données en RAM.

tu peux pas faire un define pour CsnPin....?
CsnPin, ClkPin et DataPin, sont des constantes qui ne doivent pas bouger durant l'execution du programme, car elles correspondent aux pin de sortie de l'Arduino, CsnPin (pin du Chip Select), ClkPin (pin du Clock) et DataPin(pin du Data in). Mon arduino a un ATmega2580 (Arduino Mega2560 (http://arduino.cc/en/Main/ArduinoBoardMega2560))

Citation de: spectroman le Samedi 05 Avril 2014, 19:21:23 PM

void Egaliser()
{
// definition des positions des colonnes
int colx[]= {0,4,10,16,22,28,34};
// definition des largeurs des colonnes
int larg[]= {2,4,4,4,4,4,4};
// definition des hauteurs des colonnes
int coly[]= {7,7,7,7,7,7,7};
// définition des variable de sauvegardes
int oldy[]={0,0,0,0,0,0,0};


64 octets sur la pile, assassin. >:D
Quelle pile ? je défini un tableau qui contient chaque colonne du vu-mètre. Je peux virer oldy[] dont je ne me sert plus.

Citation de: spectroman le Samedi 05 Avril 2014, 19:21:23 PM
non c'est toi qui a fait tout le boulot :D
Enfin c'est toi qui m'a expliqué pour que l'affichage fonctionne sur les 5 matrices, et d'ailleurs maintenant que je suis passé sur les AS1107, je n'ai plus besoin des condensateurs.

Pour le moment avec mon programme je n'utilise que 5% de mon arduino.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: Little_Rabbit le Samedi 05 Avril 2014, 21:59:10 PM
Salut,

Citation de: tilowil le Samedi 05 Avril 2014, 14:00:58 PM
@ petit lapin : "Alors heureux ?"  :D :D :D

Ravi !  :D

Bravo pour tes corrections !  ^-

L'équalizeur est top là ! Pour le mode Cylon, tu as raison, dans l'original "l'œil" est finalement tout petit. Sans doute avais-je en tête les robots de Berzerk ;). Mais c'est sympa comme ça aussi non ? :)

Pour tes problèmes de vitesse, effectivement avec 3 modules c'est parfait ! Ne connaissant absolument pas les AS1107 (ni l'Arduino en fait  :-\), je ne suis pas sûr d'avoir compris la cause du ralentissement... tu envoies en série la trame de chaque module, et la vitesse de cette communication série est telle que si tu dépasses 3 modules, il n'est plus possible d'avoir un taux de rafraîchissement suffisant ? Si tel est le cas, resterait-il d'autres broches sur l'arduino pour adresser en parallèle 2 blocs AS1107 (un bloc de 3 + un bloc de 2). Ainsi tu doublerais ta bande passante pour la communication avec les AS1107... Je dis ça sans avoir du tout analyser le code, et je ne sais pas notamment si c'est toi qui gère la matrice de points de chaque module, ou si l'AS1107 possède des commandes "intelligentes" de scroll dans différentes directions...

Quant aux remarques de Spectorman, je pense qu'il veut dire que la nature de tes variables ou constantes affecte le type de mémoire utilisée dans l'Arduino, et par conséquence pourrait en affecter la vitesse d'exécution. En C, un #define est véritablement une constante dont la valeur est substituée au niveau du préprocesseur C, et qui dans le code généré se traduira par une constante dont la valeur sera directement l'opérande de ton instruction assembleur (ex LDA #65 en 6502 ;) ). Une constante au sens C, de type "const byte CsnPin = 10;" n'a de constante que le fait que sa valeur ne changera jamais durant l'exécution de ton code, mais cela reste une valeur stockée dans une case mémoire exactement comme celle d'une variable. En assembleur cela se traduira potentiellement par une instruction qui ira chercher cette valeur en mémoire, puis la traitera selon l'instruction dans laquelle elle est utilisée :). En gros cela fait potentiellement un accès mémoire en plus pour rien ;).

Donc un "#define CsnPin 10" te générera probablement un code plus efficace qu'un "const byte CsnPin = 10;" ;). Spectroman confirmera (ou pas) ce que j'essaye d'expliquer :).

Quant à la pile, peut-être parle-t-il de variables locales qui sont souvent allouées dynamiquement dans le pile du microprocesseur. Je ne connais pas la taille de la pile de l'Arduino. Vue la remarque de Spectroman, j'en déduirais qu'il est peut-être luxueux d'allouer un tableau de cette taille dans la pile... Il nous apportera sûrement des précisions. :D

Bravo en tous cas pour tes avancées !  ^-

Note bien que mes remarques ne sont que le reflet de mon ressenti... Non, mes désires ne sont pas des ordres  :D.

A++
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Samedi 05 Avril 2014, 22:07:09 PM
D'abords bravo tilowil.

Oui little_rabbit, c'est que je voulais dire mais on a écrit la réponse au même moment. <:)

Citation de: tilowil le Samedi 05 Avril 2014, 20:15:22 PM
CsnPin, ClkPin et DataPin, sont des constantes qui ne doivent pas bouger durant l'execution du programme, car elles correspondent aux pin de sortie de l'Arduino, CsnPin (pin du Chip Select), ClkPin (pin du Clock) et DataPin(pin du Data in). Mon arduino a un ATmega2580 (Arduino Mega2560 (http://arduino.cc/en/Main/ArduinoBoardMega2560))
ca dois marcher si tu fais :


#define CsnPin 10    // Chip select
#define ClkPin 11    // Serial Clock
#define DataPin 12   // Serial Data


Citation de: tilowil le Samedi 05 Avril 2014, 20:15:22 PM
Quelle pile ? je défini un tableau qui contient chaque colonne du vu-mètre. Je peux virer oldy[] dont je ne me sert plus.

La mémoire se sépare en deux parties :
- une pour les variables globale
- une pour la pile et le tas (stack et heap)

exemple pour un cpu de 16K de RAM:

0x0000...0x0102 : variables globales, statiques
0x0103 => début du TAS
.....
0x3fff => début de la pile (chaque élément mis fait décroitre la pile)

Les allocations statiques, variables globales et statiques se font dans la première partie.
Les allocations dynamiques malloc, new se font sur le tas.
Les allocation des variables locales et des paramètres (si on dépasse le nombre de registres dédiés) se font sur la pile.

Le problème quand tu alloue beaucoup d'octet (c'est relatif) sur la pile, c'est que tu risque des problèmes à l'exécution.

Du genre quand je rajoute ce bout de code ça marche plus, quand je l'enlève ça remarche. Ou si j'enlève l'optimisation pour déboger plus facilement, ça marche plus. Du coup tu perds des
heures avant comprendre que le problème c'est pas le bout de code ou le compilateur, mais un problème de pile.

Quand tu dois allouer pas mal de donnés sur des petits micros, favorise les allocations statiques et dynamiques (en début de programme si possible, et sans free et delete).

Bon après je chipote, ton programme marche c'est la le but, donc je :fleche:



Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Dimanche 06 Avril 2014, 01:52:54 AM
Merci pour vos remarques à tous les 2. C'est une mauvaise habitude que j'ai prise en suivant les exemples fourni avec l'éditeur de programmation. Demain je ferais l'essai. Par contre ce qui est assez drôle, et je pense que je vais changer l'orientation de mes matrices, c'est qu'en utilisant la fonction setRow l'affichage se produit plus rapidement qu'avec la fonction setColumn. Ces deux fonction sont dérivées de ledControl (pour Max7221).

Pour répondre à ta question concernant l'affichage, je défini un buffer correspondant au nombre de colonne qu'il y a dans l'afficheur (40 dans mon cas), ensuite je transmet ce buffer directement aux AS1107 ou au Max7221 par le data in. Sachant que chaque AS1107 (ou Max 7221/7219) on une sortie data out que l'on doit relié à entrée data in du boitier suivant et ainsi de suite jusqu'au dernier boitier. le CS (Chip selector) lui est monté en sorte que chaque patte CS de chaque boitier soit connectée ensemble et à une sortie de l'Arduino. A chaque fois le buffer est affiché entièrement. C'est pour ça que dans ma vidéo  à 3 modules je cache les 2 derniers modules, car ils reproduisaient l'affichage des 2 premiers modules. En fait plus il y a de modules plus le buffer est grand et plus c'est lent. Il y a un maximum de 8 matrices par groupe. Après j'ai fait des essais non concluant pour ajouter les jeu de lumière des oreilles et des cotés. Je pense que je vais devoir revoir le programme pour faire une pseudo gestion d'interruptions afin de de pouvoir exécuter 3 programmes en même temps (visière, cotés et oreilles). Je ne suis pas près de commencer les perçages.

@Little_Rabbit : je n'ai pas pris ta remarque pour un ordre ;) je voulais juste voir ce que ça faisait, et le montrer à mon fils, c'est lui qui va porter.

je vous referai un petit topo demain soir.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Mardi 08 Avril 2014, 21:03:26 PM
Donc j'ai un peu avancé, pas beaucoup.

en ajoutant les #defines et en modifiant l'utilisation du tableau pour l'égaliseur


je n'ai pas vu de changement

J'ai commencer à travailler sur une autre version qui me permet de faire une pseudo gestion d'interruption et de lancer plusieurs tache en même temps. La mise en évidence de la différence entre l'instruction setRow et setColumn

Avec l'instruction setRow (il faut que j'oriente mes matrices différemment)


Avec l'instruction setRow (ne regardez pas le sens de défilement, je n'ai pas modifié le code, juste remplacé le setRow par setColumn)


Si je garde cette méthode, qui me permet de gérer en même temps l'affichage de la visière, du coté de la visière et des oreilles, sinon je serai obligé d'avoir un Arduino pour la visière et un Arduino pour les jeux de lumière des oreilles et des cotés de la visière.

Donc il faut que je revois ma programmation pour y intégrer tous les principes que j'avais mis en place dans ma v1. Cette nouvelle façon de faire me permet d'utiliser plusieurs scrolling (contrairement à la v1).
Je pense que la reprogrammation en utilisant les 'interruptions' va me prendre un peu de temps.

A vos avis,

A suivre...
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: Little_Rabbit le Mardi 08 Avril 2014, 22:47:34 PM
Salut,

Effectivement, les #define ne doivent optimiser le code que très légèrement, et à mon avis ça ne coince pas au niveau de la vitesse d'exécution sur l'arduino, mais en temps de transmission aux AS1107. On voit clairement que si tu limites la trame à 3 matrices, ça passe nickel.

Pour moi, comme je le disais avant, il faut augmenter ta bande passante vers les matrices de diode, en limitant une trame à 3 modules, et en mettant en // plusieurs communications vers AS1107 (chaque canal n'adressant pas plus de 3 AS1107).

La communication avec un AS1107 se fait-elle par un port d'E/S générique, et reste-t-il d'autres ports de libre ?

Je n'ai pas détaillé le programme : que fait l'arduino entre 2 bits de la trame série envoyée aux l'AS1107, ou encore, à combien de bauds se fait la communication avec l'AS1107 ? => pour moi la solution est d'adresser successivement plusieurs groupes d'AS1107.

Actuellement, tu as :
P01 (1 port d'E/S de l'arduino) vers Din
Load CS\ vers tes 5 AS1107 chaînés les uns aux autres

la trame pour charger en série 5 matrices est trop longue.

Il faudrait à la place :
P01 vers Din1
Load CS1\ qui charge 3 AS1107

P02 vers Din2
Load CS2\ qui charge 2 autres AS1107

P03 vers Din3
Load CS3\ qui charge les oreilles

Dans ta boucle de communication avec les AS1107, à la place de

Répéter
  . placer un bit PO1
  . Abaisser CS\
  . attendre
  . relever CS\
  . décaler motif pour obtenir bit suivant
jusqu'à fin de ligne


il faudrait
Répéter
  . placer un bit PO1
  . placer un bit PO2
  . placer un bit PO3
  . Abaisser CS1\
  . Abaisser CS2\
  . Abaisser CS3\
  . attendre (moins longtemps qu'avant)
  . relever CS1\
  . relever CS2\
  . relever CS3\
  . décaler motif1 pour obtenir bit suivant
  . décaler motif2 pour obtenir bit suivant
  . décaler motif3 pour obtenir bit suivant
jusqu'à fin de ligne


Tout cela est bien sûr purement hypothétique car je ne sais pas du tout comment se fait la communication avec les AS1107  :-\ :). Mais j'imagine que l'arduino pédale beaucoup plus vite que la vitesse de communication avec les AS1107, et donc qu'il doit perdre du temps à attendre que l'AS1107 puisse recevoir le bit suivant. C'est ce temps qu'il faudra utiliser pour adresser en // plusieurs groupes plutôt que de tout envoyer en série depuis un seul canal :).

Si je suis complètement à côté de la plaque, faut me le dire :D.

A+
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Mardi 08 Avril 2014, 23:38:54 PM
ton idée du l'adressage sur plusieurs bloc, c'est ce que j'utilise pour piloter 'façon interruption'. En fin de compte j'envoie à l'arduino une colonne à la fois. Comme j'ai un Arduino Mega (http://arduino.cc/en/Main/ArduinoBoardMega2560), j'ai 54 pin d'E/S. Mais au final ce sera un Arduino Nano (http://arduino.cc/en/Main/ArduinoBoardNano) pour qu'il s'intègre facilement dans le casque, sauf contrainte de dernière minute.
Car on ne peux envoyer des informations qu'a une série d'AS1107 ou Max72xx à la fois. Chaque série d'AS1107 est relié à un buffer d'affichage correspondant au nombre de colonnes de la série (40 colonnes dans mon cas).
Chaque colonne ayant une valeur comprise entre 0 et 255 (lue en binaire et correspondant au nombre de leds allumée dans la colonne de la matrice).
L'inconvénient que je vois à ta solution, qui me semble malgré tout bonne, c'est qu'avec un module de 2 matrice je serait plus rapide qu'avec un module de 3 matrices (je vais le tester quand même avec prise de video). 
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: usagi le Mercredi 09 Avril 2014, 11:50:27 AM
Je pense que le problème vient juste, de la fréquence d'écriture des AS1107. Si tu utilises deux chaines de drivers, tu as raison, tu risques de te prendre la tête pour synchroniser les deux.
La librairie que tu utilises semble écrire trop lentement dans les AS1107, je pense qu'en réécrivant seulement cette partie du code tu arrives à augmenter la vitesse d'écriture. Je t'aurais bien aider mais je n'ai rien pour tester :/ Mais je pense que la solution serait du côté des Fast PWM http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM (http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM)

// ------------------------------------------------------------------------------------
// 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 <= HighestCtrlNum) {
     chip = HighestCtrlNum -chip;
    [color=red] digitalWrite(_cspin,LOW);[/color]
     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);
     }
   }
     [color=red]digitalWrite(_cspin,HIGH);[/color]
   }
}


Pour la petite discussion sur le define/variable : si la variable est uniquement lue, le compilateur va s'en rendre compte et si il fait bien sont boulot optimisera le truc en remplaçant la variable par sa valeur. La seule différence entre le define et la variable, c'est que pour le define le remplacement sera fait à la pre-compilation tandis que la variable uniquement lue elle sera remplacée par le compilateur durant les phases d'optimisation.
Les compilo modernes font un boulot dingue sur l'optimisation.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Mercredi 09 Avril 2014, 22:41:29 PM
Je connais pas du tout les arduinos, mais ne peux tu pas utiliser le port SPI pour écrire sur AS1107?

Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Jeudi 10 Avril 2014, 00:50:12 AM
Je me suis inscrit sur le MOOC que frenchcouze a annoncé sur le forum, car il y a de la programmation Arduino (entre autre), peut être que je vais y apprendre des astuces qui me sont encore inconnue, en tant que débutant en programmation Arduino.


Citation de: usagi le Mercredi 09 Avril 2014, 11:50:27 AM
Je pense que le problème vient juste, de la fréquence d'écriture des AS1107. Si tu utilises deux chaines de drivers, tu as raison, tu risques de te prendre la tête pour synchroniser les deux.
La librairie que tu utilises semble écrire trop lentement dans les AS1107, je pense qu'en réécrivant seulement cette partie du code tu arrives à augmenter la vitesse d'écriture. Je t'aurais bien aider mais je n'ai rien pour tester :/ Mais je pense que la solution serait du côté des Fast PWM http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM (http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM)

// ------------------------------------------------------------------------------------
// 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 <= HighestCtrlNum) {
     chip = HighestCtrlNum -chip;
    [color=red] digitalWrite(_cspin,LOW);[/color]
     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);
     }
   }
     [color=red]digitalWrite(_cspin,HIGH);[/color]
   }
}


Pour la petite discussion sur le define/variable : si la variable est uniquement lue, le compilateur va s'en rendre compte et si il fait bien sont boulot optimisera le truc en remplaçant la variable par sa valeur. La seule différence entre le define et la variable, c'est que pour le define le remplacement sera fait à la pre-compilation tandis que la variable uniquement lue elle sera remplacée par le compilateur durant les phases d'optimisation.
Les compilo modernes font un boulot dingue sur l'optimisation.
Merci usagi, oui tu as raison je devrais creuser les fast PWM. Je vais lire la littérature à tête reposée.
Mais je sais dejà que mes ports correspondent à :
23   PB4 ( OC2A/PCINT4 )   Digital pin 10 (PWM)
24   PB5 ( OC1A/PCINT5 )   Digital pin 11 (PWM)
25   PB6 ( OC1B/PCINT6 )   Digital pin 12 (PWM)


Citation de: spectroman le Mercredi 09 Avril 2014, 22:41:29 PM
Je connais pas du tout les arduinos, mais ne peux tu pas utiliser le port SPI pour écrire sur AS1107?
Je ne sais pas tous les exemples que j'ai pu trouver sur le net, ils écrivaient par le pin 10, 11, 12 qui sont des ports PWM (pouvant avoir des valeurs variables de 0 à 255 ce qui correspond aux valeurs que j'ai à transmettre.
Je ne m'y connais guère plus avec cette petite bête que je découvre au fur et à mesure de mes recherches :D.

Aujourd'hui je n'ai pas eu beaucoup de temps libre pour aller faire des tests. Je serais peut être plus tranquille ce week end.

Merci à vous tous, pour vos suggestions, n'hésitez pas à continuer de m'en déposer.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: gc339 le Jeudi 10 Avril 2014, 12:20:37 PM
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?
^-
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Jeudi 10 Avril 2014, 12:21:53 PM
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+

Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Jeudi 10 Avril 2014, 13:19:43 PM
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.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: gc339 le Jeudi 10 Avril 2014, 13:41:11 PM
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. 
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Jeudi 10 Avril 2014, 15:06:09 PM
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.

Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: 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 :
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140410165735-tilowil-Platine-AS1107.jpg) (https://gamoovernet.pixhotel.fr/pics/20140410165735-tilowil-Platine-AS1107.jpg)
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: gc339 le Jeudi 10 Avril 2014, 17:11:41 PM
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 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.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Jeudi 10 Avril 2014, 17:26:49 PM
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 :
(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140410165735-tilowil-Platine-AS1107.jpg) (https://gamoovernet.pixhotel.fr/pics/20140410165735-tilowil-Platine-AS1107.jpg)

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 ;)


Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Jeudi 10 Avril 2014, 18:05:45 PM
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.

(https://gamoovernet.pixhotel.fr/pics_gamoovernet890px/20140410181254-tilowil-Platine-AS1107-v2.jpg) (https://gamoovernet.pixhotel.fr/pics/20140410181254-tilowil-Platine-AS1107-v2.jpg)
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Vendredi 11 Avril 2014, 18:19:55 PM
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)  ^-^.
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: spectroman le Vendredi 11 Avril 2014, 20:16:49 PM
Fada c'est le bon mot. Il est bien de chez nous.
Maintenant au boulot. ;)
Titre: [WIP] Réalisation d'un déguisement pour mon fils
Posté par: tilowil le Dimanche 01 Mars 2015, 20:24:18 PM
Le projet est en stand by pour une durée courte, j'espère.

Stay tuned.