In many buildings, there are sound controlled light in use. When you clap your hands, the light turns on. Now, with Raspberry Pi 3 and Windows 10 IoT, we can make a sound controlled light ourselves.

The sound sensor I use is FC-04. As other sensors, the first step is calibration.

1. Calibration for FC-04 Sound Sensor


In quiet environment. Connect VCC to DC 3.3V,GND to Ground. At that time, the power LED on the FC-04 will turn on.

If the switch LED is also on, that means the sensitivity of the sensor is too high, that will need calibration.

Turns the blue potentiometer on the FC04, and make some sound, until the moment that the switch LED is off in quiet environment and on when you make sound.

2. Connecting Raspberry Pi


This sensro has 2 output pins. DO and AO. However, if you bought the FC-04 with only DO, that will also do, we are not using AO at this project.

Connect DO to  GPIO 06.

Connect an LED, short leg to GROUND, long leg to GPIO 05.

3. Coding


First, we have 2 devices on GPIO pins, they are FC-04 and an LED. So, we need two properties for them to represent their GPIO pins.

In MainPage.xaml.cs add these 2 lines of code:

public GpioPin LedPin { get; set; }

public GpioPin SoundPin { get; set; }

We also need a flag to store the on/off status of the LED:

public bool IsLightOn { get; set; }

Register Loaded event:

public MainPage()
{
    this.InitializeComponent();
    Loaded += OnLoaded;
}

Initiate GPIO controller:

private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
    var controller = GpioController.GetDefault();
    if (null != controller)
    {

    }
}

GPIO.High will light up the LED, so when first run, we need to set it to off.

private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
    var controller = GpioController.GetDefault();
    if (null != controller)
    {
        LedPin = controller.OpenPin(5);
        LedPin.SetDriveMode(GpioPinDriveMode.Output);
        LedPin.Write(GpioPinValue.Low); // set light to off at start up
    }
}

The GPIO 06 for FC-04 is input pin, so code is:

SoundPin = controller.OpenPin(6);
SoundPin.SetDriveMode(GpioPinDriveMode.Input);

So how do we know there's a signal coming from GPIO 06? There are two ways to do it, one is by event:

//
// Summary:
//     Occurs when the value of the general-purpose I/O (GPIO) pin changes, either because
//     of an external stimulus when the pin is configured as an input, or when a value
//     is written to the pin when the pin in configured as an output.
public event TypedEventHandler<GpioPin, GpioPinValueChangedEventArgs> ValueChanged;

Another is to use a DispatcherTimer. I will use the "event" to do the project. Because Timer can not see the signal in real time. If you set interval too large, the light will become stupid. Only continuous sound will make it on and off. If interval is too small, then your light will go on and off in a very short time, it is useless.

SoundPin.ValueChanged += (pin, args) =>
{
    var pinValue = SoundPin.Read();
    if (pinValue == GpioPinValue.Low)
    {
        Debug.WriteLine("Sound Detected!");
        LedPin.Write(IsLightOn ? GpioPinValue.Low : GpioPinValue.High);
        IsLightOn = !IsLightOn;
    }
};

Here is a trick, do not use the args.Edge in the args parameter. It's not same as Read() method. The correct real-time way is to use ValueChanged event with Read()

 

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

namespace SoundLight
{
    public sealed partial class MainPage : Page
    {
        public GpioPin LedPin { get; set; }

        public GpioPin SoundPin { get; set; }

        public bool IsLightOn { get; set; }

        public MainPage()
        {
            this.InitializeComponent();
            Loaded += OnLoaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            var controller = GpioController.GetDefault();
            if (null != controller)
            {
                LedPin = controller.OpenPin(5);
                LedPin.SetDriveMode(GpioPinDriveMode.Output);
                LedPin.Write(GpioPinValue.Low); // set light to off at start up

                SoundPin = controller.OpenPin(6);
                SoundPin.SetDriveMode(GpioPinDriveMode.Input);

                SoundPin.ValueChanged += (pin, args) =>
                {
                    var pinValue = SoundPin.Read();
                    if (pinValue == GpioPinValue.Low)
                    {
                        Debug.WriteLine("Sound Detected!");
                        LedPin.Write(IsLightOn ? GpioPinValue.Low : GpioPinValue.High);
                        IsLightOn = !IsLightOn;
                    }
                };
            }
        }
    }
}

4. Running


Deploy and run the program. Clap your hand, the light turns on. Clap again, the light turns off.

When Clapping your hand, the indicator light on the FC-04 will also lights on.