dimanche 12 février 2012

Détecteur de mouvements à infrarouge et Arduino

Aujourd'hui, j'ai fait quelques expériences avec un détecteur de mouvement à infrarouge (PIR:  passive infrared) acquis sur eBay pour moins de $3 (incluant les frais de livraison à partir de Hong Kong:  comment font-ils?!?!?).

Comme c'est souvent le cas, le produit n'était accompagné d'aucune documentation, mais son utilisation est simple puisqu'il est doté de 3 broches clairement identifiées:  deux pour l'alimentation (5 V et GND) et une sortie qui prend pendant quelques secondes l'état logique "haut" si un mouvement est détecté a proximité du capteur.

Pour des informations détaillées sur le fonctionnement de ce genre de capteur, je vous conseille la page qui y est consacré sur ladyada.   J'y ai trouvé ce circuit très simple (illustré à droite) pour vérifier rapidement le bon fonctionnement du capteur.  Lorsqu'on bouge à proximité du capteur, une LED s'allume pendant quelques secondes; elle s'éteint si on demeure immobile.

Ensuite, j'ai eu envie de créer quelque chose d'un peu plus sophistiqué en mettant à contribution mon fidèle Arduino:  il s'agit d'un petit montage qui, lorsqu'il détecte votre arrivée dans une pièce, joue une petite mélodie de bienvenue.  Pour éviter que la mélodie ne soit déclenchée chaque fois que vous bougez, un délai minimal est imposé entre deux mélodies consécutives (il n'est que de 30 secondes dans le sketch ci-dessous, mais il est facile de l'augmenter à une heure, ou même plus, pour que l'Arduino vous salue uniquement lorsque vous revenez suite à une longue absence).



(Plus de détails concernant la façon de brancher un haut-parleur à l'Arduino.)




Yves Pelletier   (TwitterFacebook)

samedi 4 février 2012

Expérimentations avec un microphone à électret

Mise à jour (2 janvier 2017):  Dans cet article, je faisais un lien vers un schéma de circuit du site newcircuits, qui n'existe malheureusement plus:  je l'ai donc retiré.   Il est toutefois facile de trouver sur internet des schémas de circuits d'amplification pour micro à électret.

J'ai construit ce circuit permettant à la foi d'alimenter un microphone à électret et d'amplifier son signal.  J'ai toutefois remplacé l'amplificateur opérationnel LM358 suggéré dans le circuit original par un RC4558 car j'en avais plusieurs sous la main.

La broche du microphone qui doit être mise à la terre est celle qui communique avec le boîtier du microphone.

En branchant un oscilloscope à la sortie de l'amplificateur, on peut visualiser la forme de différents sons, en chantant près du microphone ou en l'approchant d'un instrument de musique (ici:  un synthétiseur).

Je me suis ensuite inspiré de ce sketch pour que mon Arduino détecte la présence de sons:  une LED branchée à la sortie numérique numéro 4 s'allume lorsque le microphone capte un son dépassant un seuil pré-déterminée (la sortie de l'amplificateur du microphone est branchée à l'entrée analogique numéro 4).

En fait, avec ma version du sketch ci-dessous, la LED clignote faiblement à cause des bruits ambiants, mais s'allume avec plus d'intensité lorsque le microphone capte un son suffisamment fort.



Yves Pelletier (Twitter: @ElectroAmateur)

dimanche 29 janvier 2012

Faire clignoter des LEDs avec le Launchpad (MSP430)

Voici un petit exercice d'exploration de mon nouveau Launchpad de Texas Instruments:  faire clignoter 6 LEDs l'une à la suite de l'autre, question de comprendre comment modifier l'état de chaque sortie numérique du microcontrôleur.

Je dois dire que je suis encore à la recherche d'une source de documentation qui m'expliquerait clairement les bases de la programmation de mon Launchpad.  Le site de TI explique comment le commander et comment installer les logiciels, et ensuite ça devient plutôt confus.  Les tutoriels sur internet  ne sont pas si nombreux, et réfèrent parfois à des fichiers qui ne sont plus disponibles sur le site de TI!

Le Launchpad MSP430 est muni d'entrées-sorties numériques numérotées P1.0 à P1.7, puis P2.0 à P2.5 .  Mon but était de faire clignoter l'une après l'autre 6 LEDs branchées aux ports P1.0 , P1.1 , P1.2 , P1.3, P1.4, et P2.5.

Dans un premier temps, il faut activer les sorties.  Sur Arduino, il s'agit d'écrire "pinMode(13, OUTPUT);" si on veut, par exemple, que le port numérique numéro 13 soit défini comme une sortie.

Pour le MSP430, c'est un petit peu plus compliqué:  les 8 sorties de la sortie P1 dépendent de l'état de chaque bit d'un nombre binaire stocké dans la variable P1DIR:

  • Si P1DIR vaut 00000000, alors tous les ports P1 sont des entrées.
  • Si P1DIR vaut 00000001, alors seul le port P1.0 est une sortie.
  • Si P1DIR vaut 00000010, alors seul le port P1.1 est une sortie.
  • Si P1DIR vaut 00001111, alors les ports P1.0 , P1.1, P1.2  et P1.3 sont des sorties.
C'est le même principe pour régler l'état (haut ou bas de chaque sortie).  Sur Arduino, on écrit "digitalWrite(13, HIGH);" ou ""digitalWrite(13, LOW);".  Sur le Launchpad, on règle à 0 ou 1 chaque bit d'un nombre binaire:
  • Si P1OUT vaut 00010000, alors le port P1.4 est haut, tous les autres sont bas
  • Si P1OUT vaut 11111111 alors tous les ports P1 sont hauts
  • Si P1OUT vaut 10101010 alors les ports P1.1, P1.3, P1.5 et P1.7 sont hauts.
Mais dans le programme, ce nombre doit être écrit en hexadécimal (du moins je n'ai pas trouvé de façon d'utiliser directement la version binaire).  Pour ce faire, on peut utiliser un des nombreux convertisseurs disponibles sur le web.  Ainsi, pour allumer la LED reliée à P1.0, le nombre binaire 00000001 devient 0x01.  Pour allumer la LED reliée à P1.4, le nombre binaire 00010000 devient 0x10...

L'avantage, c'est qu'on peut déterminer l'état des 8 ports en même temps au moyen d'une directive très courte.  L'inconvénient (irritant majeur en ce qui me concerne), c'est que l'écriture et la lecture du programme par un être humain devient assez arride.

Quand je programme mon Arduino, ou quand je lis un sketch Arduino réalisé par quelqu'un d'autre, j'ai l'impression de lire des instructions en Anglais qui ne sont pas très éloignées de la communication humaine:
        digitalWrite(13, HIGH);
        delay(1000);
        digitalWrite(13, LOW); 
        delay(1000); 
...Un peu comme si je disais à quelqu'un "SVP, pourrais-tu allumer la lumière numéro 13?  Attend un peu... Maintenant, éteint-là, et attend encore...

Alors que P1OUT = 0x10; suivi d'une instruction de calcul répétitif car il n'existe même pas de fonction "delay", ça me semble beaucoup moins clair...

Je continue donc d'en arriver à la même conclusion:  je préfère mon Arduino!

Ci-dessous, mon programme complet pour faire clignoter 6 LEDs:




/****************************************************************
6 LEDs clignotent en alternance.
*****************************************************************/

#include  

void delai(void)
 {
    volatile unsigned int i;
    i = 50000;        // Delai
    do (i--);
    while (i != 0);
 }


void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;         // Stop watchdog timer

  P1DIR |= 0xFF;  // toutes les sorties 1.x sont output car FF 
                  // est l'équivalent de 11111111
  P2DIR |= 0xFF;  // toutes les sorties 2.x sont output car FF 
                  // est l'équivalent de 11111111
    
  for (;;)
  {
    
    P1OUT = 0x01;       // Équivalent de 00000001  Seule la sortie 
                        // 1.0 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();

    P1OUT = 0x02;       // Équivalent de 00000010  Seule la sortie 
                        // 1.1 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();

    P1OUT = 0x04;       // Équivalent de 00000100  Seule la sortie 
                        // 1.2 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();

    P1OUT = 0x08;       // Équivalent de 00001000  Seule la sortie 
                        // 1.3 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();
    P1OUT = 0x10;       // Équivalent de 00010000  Seule la sortie 
                        // 1.4 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();
    P1OUT = 0x00;       // Toutes les sorties 1.x sont basses
    P2OUT = 0x20;       // La sortie 2.5 est haute
    delai();
                  
  }
}








Yves Pelletier (Twitter: @ElectroAmateur)