Skip to content

Implementing a New Sensor

gloveboxes edited this page Apr 10, 2015 · 2 revisions

Implementing a new Sensor

Be sure to check out the sensors and actuators that have been implemented in the Glovebox.Netduino project. See the Sensors and Actuators folders, all the code is provided to help you understand how things work.

Creating a Sensor

Inheriting from SensorBase

Your sensor class must inherit from SensorBase.

using Glovebox.MicroFramework.Base;

namespace Glovebox.Netduino.Sensors {
    public class SensorLight : SensorBase {
    }
}

Implement the Abstract Class

Next right mouse click on SensorBase to Implement the Abstract Class.

using Glovebox.MicroFramework.Base;

namespace Glovebox.Netduino.Sensors {
    public class SensorLight : SensorBase {

        protected override void Measure(double[] value) {
            throw new NotImplementedException();
        }

        protected override string GeoLocation() {
            throw new NotImplementedException();
        }

        public override double Current {
            get { throw new NotImplementedException(); }
        }

        protected override void SensorCleanup() {
            throw new NotImplementedException();
        }
    }
}

Initialise the Sensor Base Constructor

Add a Sensor Constructor and initialise the SensorBase Base constructor.

The SensorBase base constructor requires

  1. Sensor Type - arbitrary/sensible type for the sensor. The value is published alongside the sensor reading to provide some type information.

  2. Sensor Unit - arbitrary/sensible measurement unit for the sensor. Example p for percentage, n for numeric etc. The unit is published alongside the sensor reading to provide some unit information.

  3. Values Per Sample - Defines how many values will be collected per reading. Most sensors generate only one value per sample. But there are sensors that generate more data. For example a sensor that sensors both temperature and humidity.

  4. Sample Rate in Milliseconds - how often to take a sensor reading.

  5. Name - This is a unique name that you can use to identify a sensor from the command and control service.

     public SensorLight(Cpu.AnalogChannel pin, int SampleRateMilliseconds, string name)
         : base("light", "p", ValuesPerSample.One, SampleRateMilliseconds, name) {
    
         ldrAnalogPin = new AnalogInput(pin, -1);
    
         // Call StartMeasuring() after sensor initialisation
         StartMeasuring();
     }
    

Implement the sensor logic

Implement the abstract methods and properties for the Sensor class.

using Glovebox.MicroFramework.Base;
using Microsoft.SPOT.Hardware;
using System;

namespace Glovebox.Netduino.Sensors {
    public class SensorLdr : SensorBase {

        private AnalogInput ldrAnalogPin;

        /// <summary>
        /// Light Dependent Resistor Sensor Class
        /// </summary>
        /// <param name="pin">Analog Pin</param>
        /// <param name="SampleRateMilliseconds">How often to sample the sensor on milliseconds</param>
        /// <param name="name">Sensor target name for command and control</param>
        public SensorLdr(Cpu.AnalogChannel pin, int SampleRateMilliseconds, string name)
            : base("light", "p", ValuesPerSample.One, SampleRateMilliseconds, name) {

            ldrAnalogPin = new AnalogInput(pin, -1);

            // Call StartMeasuring() after sensor initialisation
            StartMeasuring();
        }


        protected override void Measure(double[] value) {
            value[0] = (int)(ldrAnalogPin.Read() * 100);
        }

        protected override string GeoLocation() {
            return string.Empty;
        }

        public override double Current {
            get { return (int)(ldrAnalogPin.Read() * 100); }
        }

        protected override void SensorCleanup() {
            ldrAnalogPin.Dispose();
        }
    }
}

Using your newly created sensor

When you reference a pin on the Netduino in your code it is important to use the SecretLabs.NETMF.Hardware.NetduinoPlus namespace not the Microsoft.SPOT.Hardware.Cpu.Pin which (unfortunately) is the Visual Studio default.

// program.cs
using Glovebox.Netduino.Sensors;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using System.Threading;

namespace MakerDen {
    public class Program : MakerBaseIoT {

        public static void Main() {

            using (SensorLdr ldr = new SensorLdr(AnalogChannels.ANALOG_PIN_A0, 1000, "ldr01")) {

                // the event handlers are implemented in the MakerBaseIoT subclass
                ldr.OnBeforeMeasurement += OnBeforeMeasure;
                ldr.OnAfterMeasurement += OnMeasureCompleted;

                // Thread sleep the main thread forever.  
                // Your newly created sensor runs on its own thread and in this case wakes up 1000 milliseconds
                Thread.Sleep(Timeout.Infinite);
            }
        }
    }
}

Or

// program.cs
using Glovebox.Netduino.Sensors;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using System.Threading;

namespace MakerDen {
    public class Program : MakerBaseIoT {

        public static void Main() {

            using (SensorLdr ldr = new SensorLdr(AnalogChannels.ANALOG_PIN_A0, -1, "ldr01")) {

                while (true) {
                    if (ldr.Current < 60) {
                        // do something...
                    }
                    else {
                        // do something...
                    }
                    // good practice not to put your netduino in to a hard loop, so add a thread sleep
                    Thread.Sleep(100);
                }
            }
        }
    }
}

Bringing it all together

The following example brings it all together and uses all the sensors and actuators defined in the IoT Solution Accelerator.

// program.cs
using Glovebox.MicroFramework.Sensors;
using Glovebox.Netduino.Actuators;
using Glovebox.Netduino.Sensors;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using System.Threading;

namespace MakerDen {
    public class Program : MakerBaseIoT {

        public static void Main() {
            Piezo speaker = new Piezo(PWMChannels.PWM_PIN_D9, "speaker01");
            speaker.BeebStartup();

            // main code marker

            //Replace the "emul" which is the name of the device with a unique 3 to 5 character name
            //use your initials or something similar.  This code will be visible on the IoT Dashboard
            StartNetworkServices("test", true);

            using (SensorTemp temp = new SensorTemp(Pins.GPIO_PIN_D8, 10000, "temp01"))
            using (SensorLight light = new SensorLight(AnalogChannels.ANALOG_PIN_A0, 1000, "light01"))
            using (SensorSound sound = new SensorSound(AnalogChannels.ANALOG_PIN_A4, 1000, "sound01"))
            using (SensorMemory mem = new SensorMemory(5000, "mem01"))
            using (rgb = new RgbLed(Pins.GPIO_PIN_D3, Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D6, "rgb01"))
            using (Relay relay = new Relay(Pins.GPIO_PIN_D7, "relay01")) {

                speaker.BeepOK();

                temp.OnBeforeMeasurement += OnBeforeMeasure;
                temp.OnAfterMeasurement += OnMeasureCompleted;

                light.OnBeforeMeasurement += OnBeforeMeasure;
                light.OnAfterMeasurement += OnMeasureCompleted;

                sound.OnBeforeMeasurement += OnBeforeMeasure;
                sound.OnAfterMeasurement += OnMeasureCompleted;

                mem.OnBeforeMeasurement += OnBeforeMeasure;
                mem.OnAfterMeasurement += OnMeasureCompleted;

                Thread.Sleep(Timeout.Infinite);
            }
        }
    }
}

This solution is publishing sensor data to the Mosquitto MQTT Service running on Microsoft Azure. The data is displayed using the IoT Dashboard.

IoT Dashboard