Une règle POV commandée par une application Android

Mais c’est quoi ?

Une règle POV (Persistence of vision : Persistance rétinienne) est une petite barre de 8 diodes (ou plus (ou même moins)) qui clignotent suivant un schéma précis. En déplaçant rapidement la règle, ce scintillement « dessine » des points qui permettent alors d’écrire un petit texte.

Il y a une foule d’exemples sur Internet ; motorisés, montés sur un ventilateur, une roue de vélo, un chien, un nunchaku, …

Voici ce que ça donne :

DSC01560-1920x1080Oui, ceci est une photographie, sans aucun montage ni aucune retouche (hormis le recadrage). Il suffit d’ouvrir l’obturateur (mode BULB), de faire son dessin, puis de le refermer. Il est nécessaire de disposer d’une télécommande pour cela.

J’ai choisi d’en fabriquer une simple, dont on peut changer le texte en utilisant un smartphone Android, par Bluetooth.

Fabriquer sa règle POV

Un peu de réflexion

Puisque les diodes représentent une colonne d’un caractère à un instant précis, il est nécessaire de « traduire » les caractères en colonnes de diodes. J’ai choisi ici de fixer la taille des caractères à 4 colonnes. Chaque colonne sera ainsi représentée par un nombre de 8-bits, le pixel du bas étant le bit de poids faible, et le pixel du haut le bit de poids fort.

Avec un tableur et une petite demie-heure, on peut dessiner pixel par pixel chaque caractères, pour les convertir en 4 nombres de 8-bits.

lettreOn construit de cette façon le tableau suivant de 380 octets, contenant tous les caractères ASCII affichables :

Calibrer le délai

Une étape importante lors du développement du programme est de choisir un délai entre deux colonnes d’un caractère. S’il est trop long, le caractère sera plat. S’il est trop court, le caractère sera étroit.

Une expérience simple permet de calibrer ce délai. Il suffit d’un chronomètre, et de votre bras :

  1. Chronométrez vous pendant un temps défini (10 secondes par exemple) et comptez des mouvements avec votre bras, comme si vous utilisiez cette règle. Par exemple, basculez le de 60 degrés puis revenez à votre position.
  2. Pour ma part, en 10 secondes, je fais 30 mouvements aller et retour, soit 60 trajets.
  3. Estimez le nombre de caractères que doit comporter un trajet. J’ai choisi 20.
  4. Maintenant, appliquer la formule suivante :
    D\'{e}lai = \frac{Temps_{total}}{Nombre_{trajets} \times Nombre_{caract\'{e}res}  \times Nombre_{colonnes}} = \frac{10}{60 \times 20 \times 4} \approx 2 ms

Le schéma

pov_bb

Le montage est trivial, même si, j’utilise un registre à décalage pour économiser des broches sur mon micro-contrôleur. Cela parait idiot puisqu’il y a largement de quoi faire avec les broches présentes sur un ATMega.

Pour le module Bluetooth, il s’agit d’un modèle chinois basé sur la puce BC417. Il n’y a aucune documentation officielle disponible, mais en cherchant « linvor » on trouve quelques informations utiles. Pour le configurer, je l’ai connecté au port série d’un PC, puis je lui ai envoyé les commandes AT suivantes :

 

 Le code pour le microcontrôleur

Je n’ai pas ajouter de commentaires, il est relativement lisible.

 L’application Android

Ici, j’ai triché un peu ; je me suis servi d’AppInventor du MIT. Il s’agit d’un outil en ligne permettant de fabriquer une application Android sans connaissance particulière.

pov_appJe vous fourni le fichier installable (APK), ainsi que le projet « source ». Il n’y a aucune garantie livrée avec ceux-ci.

Notez qu’il est nécessaire d’appairer votre smartphone avec le module Bluetooth avant de démarrer l’application.

Mise à jour: J’ai modifié mon code pour qu’il écrive le message reçu depuis le port série en mémoire, pour pouvoir le charger au redémarrage.

Fonctionnement et émulation USB d’une télécommande infrarouge pour LED RGB (Partie 1)

En traînant un peu sur le net, je suis tombé sur des bandes de diodes RGB (rouge/vert/bleu) contrôlées par télécommande (44 boutons) pour une trentaine d’euros les dix mètres. Il s’agit d’un clone chinois des lampes Living Colors de Phillips.

Après l’avoir installé et joué un peu avec l’éclairage, j’ai cherché à savoir comment celui-ci fonctionne ; l’idée étant de pouvoir contrôler le tout depuis un PC.

J’aurais pu démonter le boitier de commande de la bande de diodes, mais cela m’aurait forcer à tirer un second câble (en plus de l’alimentation) du PC jusqu’à la bande de diode, ce qui n’est pas pratique. Alors pour le défi, j’ai cherché à savoir comment fonctionne la télécommande, et comment émuler ses fonctions.

Télécommande RGB

S’équiper à moindre frais

Si vous disposez d’un PC avec une entrée pour micro, vous n’aurez pas besoin d’investir dans beaucoup de matériel. Prenez une prise jack mâle, une diode infrarouge réceptrice, une résistance de 4.7kΩ et un peu de fil.

irda_schema

Puis, téléchargez le logiciel Audacity (open-source). Il s’agit d’un éditeur de signal sonore, dont l’interface est un peu rude, mais il est très simple à utiliser.

Il suffit maintenant de choisir la bonne source de son, et de démarrer la capture. Un petit clic sur un des boutons de la télécommande, et hop !

irda_large

C’est quoi ce bazar ?!

Ici, on récupère le signal émis par la télécommande, mais seulement, celui-ci est échantillonné a 44100Hz. C’est bien pour « lire » le signal, mais ceci ne suffit pas à l’émuler.

Il est nécessaire de comprendre comment fonctionne, en théorie, le signal infrarouge.

La théorie (oui, il en faut un peu tout de même)

L’infrarouge est un signal très rudimentaire, qui à la fâcheuse tendance d’être sensible à la chaleur. En effet, toute source de chaleur (corps vivant, soleil, ampoule, …) émet naturellement des rayonnements infrarouges. Cela peut interférer avec le transfert d’un signal. Il n’est donc pas possible de considérer la présence d’un rayonnement comme un [ccie]1[/ccie] et l’absence comme un [ccie]0[/ccie].

On va alors utiliser un signal pulsé à une fréquence particulière. Ainsi, un [ccie]1[/ccie] sera un signal pulsé d’une durée déterminée, tandis qu’un [ccie]0[/ccie] sera un silence de même durée. Ceci implique de synchroniser le signal sur une fréquence particulière.

Rendered by QuickLaTeX.com

Pour déterminer cette fréquence, la méthode du microphone atteint ses limites ; il faudrait ici un oscilloscope avec une fréquence d’échantillonnage d’au moins une centaine de kilohertz. À défaut, il faut chercher un peu.

Prenons le signal acquis, et observons le. On a :

  • une longue crête de ~9ms
  • une longe crête de ~4.5ms
  • 4 paquets de 16 crêtes de ~0.5ms ou ~1.5ms

En fouillant, je suis tombé sur cet article (en anglais). Il s’agit du protocole infrarouge NEC.

On y est presque !

Le protocole NEC

Il s’agit d’un code, utilisant une fréquence de 38kHz (soit une modulation de 26.3µs) et dont le protocole est :

  • initialisation par un signal pulsé de 9ms (342 modulations), suivi d’un silence de 4.5ms
  • adresse du matériel (ici 0x00) sur 8 bits
  • inverse de l’adresse sur 8 bits
  • commande (ici 0x02 pour « POWER ») sur 8 bits
  • inverse de la commande sur 8 bits

Pour la transmission de l’adresse et de la commande, on code chaque bit de la façon suivante (le bit fort en premier) :

  • un signal pulsé de 560µs (21 modulations), suivi d’un silence de même durée pour [ccie]0[/ccie]
  • un signal pulsé de 560µs, suivi d’un silence de 1690µs pour [ccie]1[/ccie]

Voici ce que donne donc la trame qui permet l’allumage (ou l’extinction) des diodes :

Rendered by QuickLaTeX.com

Mettons cela en pratique

Il suffit de prendre un microcontrôleur (un ATTiny85 peut suffire, mais j’ai préféré prendre un ATMega168 pour ajouter une connexion série par la suite) et d’y brancher une diode infrarouge (émettrice cette fois).

Voici un code minimaliste qui se contente d’allumer et d’éteindre toutes les secondes. Vous y trouverez également les commandes disponibles en macro.

[cce_c]
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>

#define IR_PORT    PORTD
#define IR_DDR     DDRD
#define IR_PIN    PD2

#define SIGNAL_BOTTOM()    IR_PORT |= (1<<IR_PIN)
#define SIGNAL_TOP()    IR_PORT &= ~(1<<IR_PIN)
//38kHz
#define PULSE()        {SIGNAL_TOP();_delay_us(13.2);SIGNAL_BOTTOM();_delay_us(13.2);}

#define CMD_UP        0x3A
#define CMD_DOWN    0xBA
#define CMD_PLAY    0xB2
#define CMD_POWER    0x02

#define CMD_RED        0x1A
#define CMD_GREEN    0x9A
#define CMD_BLUE    0xA2
#define CMD_WHITE    0x22

#define CMD_DEEPORANGE    0x2A
#define CMD_LIGHTGREEN    0xAA
#define CMD_DEEPBLUE    0x92
#define CMD_HOTWHITE    0x12

#define CMD_ORANGE    0x0A
#define CMD_LIGHTBLUE    0x8A
#define CMD_PURPLE    0xB2
#define CMD_WARMWHITE    0x32

#define CMD_BROWN    0x38
#define CMD_TURQUOISE    0xB8
#define CMD_PINK    0x78
#define CMD_COLDWHITE    0xF8

#define CMD_YELLOW    0x18
#define CMD_CYAN    0x98
#define CMD_MAGENTA    0x58
#define CMD_ICEWHITE    0xD8

#define CMD_RED_UP    0x28
#define CMD_GREEN_UP    0xA8
#define CMD_BLUE_UP    0x68
#define CMD_QUICK    0xE8

#define CMD_RED_DOWN    0x08
#define CMD_GREEN_DOWN    0x88
#define CMD_BLUE_DOWN    0x48
#define CMD_SLOW    0xC8

#define CMD_DIY1    0x30
#define CMD_DIY2    0xB0
#define CMD_DIY3    0x70
#define CMD_AUTO    0xF0

#define CMD_DIY4    0x10
#define CMD_DIY5    0x90
#define CMD_DIY6    0x50
#define CMD_FLASH    0xD0

#define CMD_JUMP3    0x20
#define CMD_JUMP7    0xA0
#define CMD_FADE3    0x60
#define CMD_FADE7    0xE0

void init_sequence(){
uint8_t i;
for(i = 0; i<255; i++) PULSE();
for(i = 0; i<88; i++) PULSE(); //too lazy too swap to uint_16t (love your memory)
_delay_us(4500);
}

void send(uint8_t bit){
int8_t i;
for(i = 0; i<21; i++) PULSE();
if (bit & 0x01) _delay_us(1130);
_delay_us(560);
}

void send_command(uint8_t address, uint8_t command){
init_sequence();
int8_t i;
for(i=7;i>=0;i–) send(address >> i);
for(i=7;i>=0;i–) send(~address >> i);
for(i=7;i>=0;i–) send(command >> i);
for(i=7;i>=0;i–) send(~command >> i);

}

int main(){
IR_DDR = (1<<IR_PIN);
for(;;){
send_command(0x00,CMD_POWER);
_delay_ms(1000);
}
}
[/cce_c]

Ou quelque chose de plus funky :

[cce_c]
int main(){
IR_DDR = (1<<IR_PIN);
for(;;){
send_command(0x00,CMD_TURQUOISE);
_delay_ms(100);
send_command(0x00,CMD_ORANGE);
_delay_ms(100);
send_command(0x00,CMD_PURPLE);
_delay_ms(100);
}
}
[/cce_c]

Supprimer le bruit d’un chargeur QI XCSource

Possédant un Nexus 4, je cherchais un chargeur QI (La technologie QI permet de recharger un appareil compatible, sans contact, grâce à l’induction) pour en finir avec les câbles. Je suis tombé sur cette référence chez Amazon : à 20€, là où les autres sont généralement vendus entre 30 et 80€, j’ai voulu faire le test.

Je ne connais pas la marque XCSource, les avis étaient peu nombreux au moment de commander, mais maintenant, tout le monde s’accorde sur le fait que le bruit émis au moment de la mise en charge est insupportable.

Un bip, ca va deux bips…

D’autant plus, lors de la fin de la charge, celui-ci s’arrête automatiquement, ce qui autorise la décharge de la batterie du téléphone qui va de nouveau enclencher le cycle du chargeur, lequel poussera fièrement son cri strident, malgré l’heure (3h du mat) ou le lieu (au bureau).

J’ai donc souhaité l’ouvrir, et faire taire cette bête une fois pour toute.

Ouvrons la bête !

Un tournevis fin et plat suffit à démonter la coque du chargeur, le long de son arête. Voici ce qu’on y trouve.

XSource - entraille 1

En dessous de la puce centrale, vous pouvez apercevoir un capot où se cache ce maudit buzzer.Une flèche sur celui-ci vous indique où insérer votre tournevis pour l’ouvrir.

XSource - entraille 2

Une fois ouvert, vous trouverez un petit disque de métal. C’est lui qui émet ce bruit insupportable en vibrant. Il suffit donc de l’enlever. Ce qui laissera apparaitre la bobine.XSource - entraille 3

Une fois le disque retiré, vous pouvez remettre le capot, et refermer le chargeur.

Vous pouvez maintenant profiter d’un rechargement sans fil et en silence !