Détecter des mouvements depuis un capteur avec du Windows 10 IoT Core

Cet article fait partie d'une série concernant Windows 10, le Raspberry Pi 2 et l'IoT en général.

Maintenant que nous savons allumer une LED, on va tenter de récupérer des données depuis une capteur de mouvement PIR.

Voici les autres articles de la série :

Pré-requis

Logiciels et matériel

Capter les données du détecteur de mouvement en C#

Réaliser le montage

Nous pouvons déjà repartir du montage précédent, nous allons simplement lui ajouter une seconde LED et notre capteur de mouvement.

Pour le branchement :

  • Repartir du circuit précédent
  • Ajouter une 2ème LED branchée sur un port GPIO (numéro 5 dans mon cas)
  • Brancher le capteur PIR :
    • Fil noir sur le Ground (GND)
    • Fil rouge sur du 5V
    • Fil jaune sur un GPIO (18 chez moi)

Voici à quoi devrait ressembler le nouveau montage :
Placement des éléments sur le Breadboard
Placement des éléments sur le Breadboard

Le code

Modifions un peu le code écrit précédemment.

J'ai tout d'abord créé une classe Peripheral qui permet d'initialiser correctement un périphérique, mais aussi de faire les différentes vérifications à un seul endroit et sans se répéter. Elle nous permet aussi de récupérer le statuts renvoyé par un élément et de renvoyer l'Event ValueChanged. J'ai de plus implémenté l'interface IDisposable :

using System;
using Windows.Devices.Gpio;
using Windows.Foundation;

namespace MotionDetector
{
    class Peripheral : IDisposable
    {
        protected int _status = 0;
        protected int _pin;
        protected GpioPin _gpioPin;
        protected bool _disposed = false;

        public Peripheral(int pinId) : this(pinId, 0)
        {

        }

        public Peripheral(int pinId, int status)
        {
            _pin = pinId;
            _status = status;

            var gpio = GpioController.GetDefault();

            if (gpio == null)
            {
                _gpioPin = null;
                return;
            }

            _gpioPin = gpio.OpenPin(_pin);
        }

        public int GetStatus()
        {
            return (int)_gpioPin.Read();
        }

        public int GetPinId()
        {
            return _pin;
        }

        public event TypedEventHandler<GpioPin, GpioPinValueChangedEventArgs> ValueChanged
        {
            add
            {
                _gpioPin.ValueChanged += value;
            }
            remove
            {
                _gpioPin.ValueChanged -= value;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if(_disposed)
            {
                return;
            }
            if (disposing) 
            {
                _gpioPin.Dispose();
            }
            _disposed = true;
        }
    }
}

J'ai ensuite créé une classe Led qui hérite de Peripheral, elle lui ajoute juste de quoi changer l'état de la LED :

using Windows.Devices.Gpio;

namespace MotionDetector
{
    class Led : Peripheral
    {
        public Led(int pinId) : base(pinId)
        {

        }

        public Led(int pinId, int status) : base(pinId, status)
        {
            _gpioPin.Write(GpioPinValue.High);
            _gpioPin.SetDriveMode(GpioPinDriveMode.Output);
        }

        public void ChangeStatus()
        {
            if(_status == 1)
            {
                ChangeStatus(false);
            }
            else
            {
                ChangeStatus(true);
            }
        }

        public void ChangeStatus(bool status)
        {
            if (status)
            {
                _gpioPin.Write(GpioPinValue.Low);
                _status = 1;
            }
            else
            {
                _gpioPin.Write(GpioPinValue.High);
                _status = 0;
            }
        }
    }
}

Et enfin dans notre main :

using Windows.Devices.Gpio;
using Windows.UI.Xaml.Controls;

namespace MotionDetector
{
    public sealed partial class MainPage : Page
    {
        private Led redLed = null;
        private Led greenLed = null;
        private Peripheral pirPeripheral = null;

        public MainPage()
        {
            this.InitializeComponent();

            MotionDetector();
        }

        private void MainPage_Unloaded(object sender, object args)
        {
            // Clean
            pirPeripheral.Dispose();

            redLed.Dispose();
            greenLed.Dispose();
        }

        private void MotionDetector()
        {
            redLed = new Led(5, 0);
            greenLed = new Led(6, 0);
            pirPeripheral = new Peripheral(18, 0);

            // Red Led on by default, Green Led off
            redLed.ChangeStatus(true);
            greenLed.ChangeStatus(false);
        }
    }
}

On va maintenant simplement ajouter de quoi capter l'Event ValueChanged de notre capteur PIR (dans la fonction MotionDetector) :

pirPeripheral.ValueChanged += PirPin_ValueChanged;

Et voici l'Event Handler correspondant :

private void PirPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
{
    int pirPinStatus = pirPeripheral.GetStatus();

    if (pirPinStatus == 0)
    {
        redLed.ChangeStatus(true);
        greenLed.ChangeStatus(false);
    }
    else
    {
        redLed.ChangeStatus(false);
        greenLed.ChangeStatus(true);
    }
}

Résultat

Il ne nous reste plus qu'à déployer et voir si le tout fonctionne.

Notre application devrait allumer la LED verte à chaque mouvement détecté, et la LED rouge le reste du temps.

La LED verte s'allume quand un mouvement est détecté

Il est possible que la LED verte reste allumée quelques secondes, c'est normal, ça varie un peu en fonction de la qualité de votre capteur PIR, rien de grave là-dedans.
Vous pouvez aussi régler la sensibilité et la durée de détection de votre capteur avec les deux petites vis à l'arrière

Les vis permettant de régler notre capteur PIR

Dans le prochain article, nous verrons comment envoyer les différentes données captées sur un service Azure.