BAM sur TINY

Bonjour à tous.

BAM BIM BOUM ? Mais qu'est-ce qu'il raconte le Barbudor ?
La marmotte sortirait-elle de son trou(1) avec quelques neurones en moins?

La lecture du récent blog-post de notre ami Skywodd sur le BCM/BAM(2) m'a récemment rappelé que je voulais depuis plusieurs mois tester cette méthode sur le petit ATTiny85 qui sert à faire clignoter une de mes guirlandes de noël (autant se préparer en avance, l'évènement approche à grands pas...).

Ceux qui ont joué avec le Tiny savent qu'il manque cruellement de sorties PWM. On ne peut en utiliser que 3 alors que ma guirlande a 4 branches. Résultat l'une des branches ne fonctionnait jusqu'à présent qu'en tout-ou-rien.
Une technique pour faire plus de PWM est d'utiliser le SoftPWM de façon a reproduire par soft avec de nombreuuuuuses interruptions timer des signaux rectangulaires qui présentent la même forme d'onde qu'une sortie PWM hard (c'est à dire 1 durée haute et 1 durée basse dont le rapport (duty-cycle/rapport-cyclique) contrôle l'énergie dans la LED. Ainsi typiquement pour gérer un PWM à 256 niveaux (0..255) on va utiliser 255 interruptions timer par cycle afin de pouvoir ajuster indépendamment le rapport cyclique de chacun des signaux à traiter. Inconvénient, beaucoup d'interruptions inutiles et donc beaucoup de perte d'efficacité du processeur.

Le principe du BAM est basé sur le fait qu'il n'est nul besoin de respecter cette forme régulière rectangulaire. Il est possible d'arriver au même résultat avec des formes plus compliquées mais qui en moyenne ont le même rapport somme-des-temps-hauts sur somme-des-temps-bas que le rectangulaire de base.
Il s'avère qu'ainsi on n'a besoin pour gérer 256 niveaux non plus de 255 interruptions par période mais seulement de 8! Mais au lieu qu'elles soient régulièrement espacées, elles suivent une progression géométrique afin de porter le "poids" de chacun des bits quelle représente.

Exemple avec 16 niveaux de 0 à 15 (4 bits de codage).

Soft PWM :

Temps :          EF123456789ABCDEF1234
Interruptions :  .....................  Haut  Bas
Led1=2  :        __--_____________--__     2   13
Led2=8  :        __--------_______----     8    7
Led3=9  :        __---------______----     9    6
Led4=14 :        -_--------------_----    14    1
Led5=15 :        ---------------------    15    0

En mode BAM, chaque période de temps entre les interruptions va représenter le poids du bit
Entre l'interruption 1 et l'interruption 2 s'écoule le temps du bit 0
Entre la 2 et la 3, le temps représente le bit 1 (et donc dure 2 fois plus longtemps que le précédant)
A chaque fois, la durée entre interruption double jusqu’au dernier bit

Temps :          F123456789ABCDEF12345
Interruptions :   .. .   .       .. .   Haut      Bas
Led1=2  :        __--_____________--__  2         1+4+8=13
Led2=8  :        ________--------_____  8         1+2+4=7
Led3=9  :        _-______--------_-___  8+1=9     2+4=6
Led4=14 :        -_-------------------  2+4+8=14  1
Led5=15 :        ---------------------

Quelques liens pour approfondir en plus de l'article de Skywodd :
http://blog.spitzenpfeil.org/wordpress/2012/01/11/rgb-led-ring-v2-sequels-dont-have-to-be-bad/

Et bien sur en pièce jointe le code pour ATtiny85 (en utilisant l'environement arduino-tiny :

Amusez vous bien.

(1) La marmotte Barbudor est d'une race qui mange et dord à n'importe qu'elle époque de l'année.
(2) Quoi ? Vous n'avez pas encore lu cet article ? -> [Présentation] Modulation codée binaire (B.C.M.) | Skyduino - Le DIY à la française

guirlande_4.ino (8.62 KB)

bonjour barbudor
content de te relire 8)
j'avais "diagonalé" l'article de skywodd
J'avais envisagé de jouer avec du tiny , c'est peut etre là un bon pretexte
http://forum.arduino.cc/index.php?topic=172898.msg1285348#msg1285348

Salut,

Dans le cas d'une PWM avec les broches du microcontrôleur lui même il existe une autre solution.
En gros il suffit de placer toutes les broches à HIGH puis d'attendre un temps t = min(t0, t1, t2, ...)
(avec tn = temps avant basculement de la broche n)
Ça demande de trier par ordre croissant les temps tn dans un tableau mais niveau CPU c'est tiptop et en plus c'est "servo-friendly".

La méthode de modulation BCM c'est vraiment ultra efficace avec des registres à décalages.
Petite anecdote : pour les matrices de leds que je bricole en ce moment j'arrivai à un malheureux 30Hz de rafraichissement en TTL en dédiant 50% du temps cpu à l'affichage.
Avec cette méthode je me demande sérieusement ce que je vais bien pouvoir faire de 4096 couleurs (32768 bientôt) à 30Hz :grin:
Et vu que j'aurai 2/3 de temps cpu libre il va falloir que je trouve une occupation à mon ATmega :grin:

barbudor:
(1) La marmotte Barbudor est d'une race qui mange et dort à n'importe qu'elle époque de l'année.

On doit être de la même espèce 8)

Artouste:
j'avais "diagonalé" l'article de skywodd

Roo ça c'est pô bien, j'ai mis tout mon petit cœur dans la rédaction de ces slides :grin:

skywodd:

Artouste:
j'avais "diagonalé" l'article de skywodd

Roo ça c'est pô bien, j'ai mis tout mon petit cœur dans la rédaction de ces slides :grin:

:grin:

tu aurais préféré que je le mette de coté ? :grin:
c'etait un compliment 8)
une diagonale étant inévitablement plus longue qu'un des cotés :stuck_out_tongue:

skywodd:
Salut,

Salut :wink:

Dans le cas d'une PWM avec les broches du microcontrôleur lui même il existe une autre solution.
En gros il suffit de placer toutes les broches à HIGH puis d'attendre un temps t = min(t0, t1, t2, ...)
(avec tn = temps avant basculement de la broche n)
Ça demande de trier par ordre croissant les temps tn dans un tableau mais niveau CPU c'est tiptop et en plus c'est "servo-friendly".

C'est exact, un peu plus ch... et pas besoin de faire la rotation des bits.
Par contre c'est plus efficace seulement si tu as moins de broches à gérer que de bits.
Dans mon cas, sur l'ATTiny j'ai au plus 5 sorties et j'ai choisit de me limiter à 6 niveaux. Dans les 2 cas çà donne 6 interruptions par cycle.

Tu utilises quoi pour ta matrice ? Des '595 coté cathode ? ou des drivers de courant genre MBI5168 / MBI5030 ?
Et coté Anode ? Des '595 aussi ?
J'ai justement une matrice 8x8 que je veux mettre en route d'ici à noël soit avec un ATmega168/328 soit un ATtiny.

Un truc qui me gène pour la matrice 8x8 c'est que au mieux un led va être alimenté 1/8eme du temps. Hors d'après la plupart des datasheet de LED, le courant max impulsionnel supporté est de l'ordre de 3 à 4 fois le courant permanent. Donc pas possible d'alimenter en impulsionnel à 160mA ? Donc pas possible d'avoir l'intensité max ?