This example implements a new .NET Gadgeteer module from an Infrared Phototransistor and a 10 kilo ohm pull-up resistor. It uses the GHI Electronics Extender Module to connect the simple hardware. The output activates binary logic on a general-purpose digital input/output pin, operating at 3.3 volts. This case is not difficult to understand. Many other binary operations can be done the same way.
<Note: A new post dated November 11, 2011 shows how to implement a Web service to record data from this sensor when it is activated. See: http://wp.me/p1TEdE-5L >
The following schematic shows the phototransistor circuit. The voltage, V out, transitions from the low state to the high state when light is detected.
The following video demonstrates the operation of the light sensor module in a .NET Gadgeteer application with the GHI Electronics Fez Spider Mainboard and a Multicolor LED. When the sensor is exposed to light it raises an event that is handled by C# application code and starts the MulticolorLED blinking. This event could be used to activate other modules such as a camera module or an alarm.
The following illustration shows the light sensor using the phototransistor as implemented for testing on a bread board. (See also: How to build a simple sensor module)
Socket Types and Pin Mappings for a new .NET Gadgeteer Module
The .NET Gadgeteer Builder Guides contain an important reference when you are creating new modules. The Socket Types Table identifies the functionality each socket and pin supports. Modules, such as this light sensor, that only require a general-purpose digital input/output pin, operating at 3.3 volts, can be implemented on an X or Y type socket. An X type socket supports general-purpose digital input/output (GPIO) on pins 3, 4, or 5. The 3.3 volt input for the module is on pin 1. The ground is on pin 10.
The collector side of the phototransistor and the pull-up resistor connect to the 3.3 voltage source on pin 1. The emitter connects to ground. The output connects to the GPIO pin; this example uses pin 4.
This module uses the GHI Electronics Extender Module to connect the phototransistor to the mainboard as shown in the following illustration.
Using the Module Builder Template for a new .NET Gadgeteer Module
The hardware driver for this .NET Gadgeteer module is easy to implement using the .NET Gadgeteer Module Template, which can be downloaded from the .NET Gadgeteer CodePlex site. The download package includes other useful builder templates with everything needed to implement drivers for .NET Gadgeteer modules, mainboards, and installation packages for modules and kits.
Download and install the templates by using the GadgeteerBuilderTemplates-2.41.301.msi. The new Visual Studio project types will include the template options under the Gadgeteer subsection. Select .NET Gadgeteer Module.
The new project will open to a readme.txt file that describes the driver implementation process. This module requires only a few name changes and the assignment of the output pin and resistor type, pull-up or pull-down.
For this module the only changes to the code provided by the template are the output pin assignment and resistor mode in the constructor: GT.Socket.Pin.Four GTI.ResistorMode.PullUp.
// Note: A constructor summary is auto-generated by the doc builder. /// <summary></summary> ///socketNumber">The socket that this module is plugged in to. public LightSensor(int socketNumber) { // This finds the Socket instance from the user-specified socket number. // This will generate user-friendly error messages if the socket is invalid. // If there is more than one socket on this module, then instead of "null" for the last parameter, // put text that identifies the socket to the user (e.g. "S" if there is a socket type S) Socket socket = Socket.GetSocket(socketNumber, true, this, null); // This creates an GTI.InterruptInput interface. The interfaces under the // GTI namespace provide easy ways to build common modules. // This also generates user-friendly error messages automatically, // e.g. if the user chooses a socket incompatible with an interrupt input. this.input = new GTI.InterruptInput(socket, GT.Socket.Pin.Four, GTI.GlitchFilterMode.On, GTI.ResistorMode.PullUp, GTI.InterruptMode.RisingAndFallingEdge, this); // This registers a handler for the interrupt event of the interrupt input (which is below) this.input.Interrupt += new GTI.InterruptInput.InterruptEventHandler(this._input_Interrupt); }
Follow the first three steps of the instructions in the readme.txt file, build the project, and at step four, you are ready to test the module. Add a test project to the solution of the type demonstrated in other posts in this blog. Add a reference to the new module in the test project. Add a MultiColorLed by using the designer and connect it to socket 11. The light sensor module does not yet have a display image, so you’ll have to instantiate this test module in the Program.cs file rather than by using the Designer.
My module uses the name of this blog for ManufacturerName: Gadgeteer.Modules.IntegralDesign.LightSensor. It is declared and instantiated in the following code segments with the Gadgeteer.Modules.GHIElectronics.MulticolorLed that will flash when light activates the sensor.
Declare the module as a global entity in the TestLightSensor Program class.
// LightSensor declaration. Gadgeteer.Modules.IntegralDesign.LightSensor lightSensor;
Instantiate the module in the ProgramStarted() method.
// LightSensor test module initialization. lightSensor = new GTM.IntegralDesign.LightSensor(4);
Using the Events raised by a new .NET Gadgeteer Module in Application Code
Now that you have instance of the new module, you can use it like any other .NET Gadgeteer module with Intellisense to create event handlers for the input interrupt events that occur when the output goes high and low.
The code for this test application is simple. It starts a MulticolorLed blinking red when light activates the sensor and then turns the led off when the light source is extinguished. In this test case, the light is extinguished by covering the sensor, as shown in the video demo at the beginning of this discussion. Build the test application in debug mode and set it as the start-up project of the solution.
using System; using Microsoft.SPOT; using Microsoft.SPOT.Presentation; using Microsoft.SPOT.Presentation.Controls; using Microsoft.SPOT.Presentation.Media; using GT = Gadgeteer; using GTM = Gadgeteer.Modules; using Gadgeteer.Modules.GHIElectronics; namespace TestLightSensor { public partial class Program { // LightSensor declaration. Gadgeteer.Modules.IntegralDesign.LightSensor lightSensor; void ProgramStarted() { // LightSensor test module initialization. lightSensor = new GTM.IntegralDesign.LightSensor(4); lightSensor.LightSensorHigh += new GTM.IntegralDesign.LightSensor.LightSensorEventHandler(lightSensor_LightSensorHigh); lightSensor.LightSensorLow += new GTM.IntegralDesign.LightSensor.LightSensorEventHandler(lightSensor_LightSensorLow); Debug.Print("Program Started"); } void lightSensor_LightSensorLow(GTM.IntegralDesign.LightSensor sender, GTM.IntegralDesign.LightSensor.LightSensorState state) { led.TurnOff(); } void lightSensor_LightSensorHigh(GTM.IntegralDesign.LightSensor sender, GTM.IntegralDesign.LightSensor.LightSensorState state) { led.BlinkRepeatedly(GT.Color.Red); } } }
Editing the GadgeteerHardware XML File for a new Gadgeteer Module
The elements of the GadgeteerHardware.XML file specify the details of a new module’s implementation, including such things as the manufacturer, UUID, whether the module supplies power to the system, dimensions of the module in millimeters, the minimum version of .NET Gadgeteer Core libraries required, the URL of support information, the assembly that contains the software for the module, and finally socket and pin specifications.
The following example shows the GadgeteerHardware.XML file for this LightSensor module after a few small changes were made to the file that the template provided. The module uses socket X or socket Y. It doesn’t have any electrical connection to pin 3, so that pin specification has been commented out: . The module doesn’t use socket type S, so that entire element of the XML is commented out. The module doesn’t require libraries for other mainboards or modules, so that entire section is commented and can be removed. The example below shows the modified file; see the GadgeteerHardware.XML file in a new project for the complete template.
xml version="1.0" encoding="utf-8" ?> <!-- This module definition should be filled in. Mouse over any attribute name to get more help about that attribute. --> <!-- The Unique ID is auto-generated and does not usually need to be modified. --> <!-- This lists the assembly which provides the API to this module, i.e. the output assembly of this template. --> <!-- This is an example socket specification with two sockets on the board. The socket positions are specified in mm from the top left corner of the board, with the orientation 90 indicating the socket notches are pointing upwards (0=right, 180=left, 270=down) --> <!-- This example socket is compatible with socket types <span class="hiddenSpellError">XY</span> which has electrical connections to pins 3 and 4 --> X Y <!--3--> 4 <!-- This example socket is compatible with socket type S, it is optional, and it has electrical connections to pins 3,4,5,7,8,9, with 7,8,9 being <span class="hiddenSpellError">shareable</span> (SPI bus) --> <!-- S 3 4 5 7 8 9 --> <!-- Use this tag if the module requires specific libraries provided by the <span class="hiddenSpellError">mainboard</span> or by other modules --> <!-- --> <!-- Use this tag if the module provides libraries that may be required by other modules--> <!-- --> <!-- Use the <span class="hiddenSpellError">ProvidedSocket</span> tag if this module provides a socket that another module can plug into --> <!-- The example below is for <span class="hiddenSpellError">DaisyLink</span> modules which provide a socket type "*" --> <!-- * -->
Creating the Designer Image for a new .NET Gadgeteer Module
As described in the readme.txt file, you can replace Image.jpg in the Resources folder of the LightSensor project with an image of the module that will be used by the .NET Gadgeteer Designer. Users will be able to drag and drop the module from the Visual Studio toolbox to the Designer surface, and the image will show the module and enable the Designer to display and connect the module to the right socket on a mainboard.
Overwrite Resources\Image.jpg with a good quality top-down image of the module with the socket side facing up, cropped tight (no margin), in the same orientation as the width and height specified in GadgeteerHardware.xml.
Creating an Installer Package for a new .NET Gadgeteer Module
The Setup folder in the new module project includes everything you need to create an installation package for the new module. A few simple changes to the file Setup\common.wxi will specify parameters for the installer. You don’t have to modify any other file in the Setup directory. The common.wxi file, as shown below, describes the specification very well. The modifications for this LightSensor are similar to previous settings.
<!-- This file includes global constants for the module installer. Module manufacturers should change the below to customise this template to their module. --> <!-- Change this whenever building a new installer. The fourth number is ignored, so change one of the top three. Otherwise, users will not be able to upgrade properly; Windows Installer will exit with an error instead of upgrading. --> <!-- Also change the version numbers in Properties/AssemblyInfo.cs --> ModuleSoftwareVersion = "1.0.0.0" ?> spaces/punctuation. --> SafeModuleName = "LightSensor" ?> without any spaces/punctuation. --> SafeManufacturer = "IntegralDesign" ?> manufacturer name in add/remove programs. --> FullManufacturer = "Integral Design" ?> <!-- No need to change anything below this line. --> OutputFileName = "GTM.$(var.SafeManufacturer).$(var.SafeModuleName)"?> RegistryKeyNetMF41 = "SOFTWARE\Microsoft\.NETMicroFramework\v4.1\AssemblyFoldersEx\$(var.OutputFileName)"?> RegistryKeyVSAddin = "SOFTWARE\Microsoft\.NETGadgeteer\v2\HardwareDefinitionFolders\$(var.OutputFileName)" ?>
To build the project in release mode, select Release option from the drop-down menu as shown in the following illustration.
Building the project in release mode takes more time than building in Debug mode. The output of release build includes the file LightSensor.msi, which will be found in the $LightSensor\LightSensor\bin\Release\Installer folder. Run this MSI to install the new LightSensor module for use by the .NET Gadgeteer Designer.
Testing the Installed Release Mode Implementation of a new .NET Gadgeteer Module
Create a new .NET Gadgeteer application and add a reference to the LightSensor module, release version, found at $LightSensor\LightSensor\bin\Release\NETMF\GTM.IntegralDesign.LightSensor.dll. Now you should see the module in the Designer Toolbox as shown in the following illustration.
Drag the module to the Designer surface, click on the module socket and hold down the mouse button; the sockets that support the X or Y connection will turn green on the Mainboard image as shown in the following illustration. The image for this experimental bread board module is inelegant. Refer to the Module Builder’s Guide for the specifications of production modules.
Drag a connection to socket number 4 on the Fez Spider Mainboard as shown below.
Save the Designer file in Visual Studio, and close the Designer.
To run the test application, use the same code as in the test application, without the declaration and instantiation of the LightSensor, as shown in the following code. The demo should run just as the test application did before building and running the installer.
using System; using Microsoft.SPOT; using Microsoft.SPOT.Presentation; using Microsoft.SPOT.Presentation.Controls; using Microsoft.SPOT.Presentation.Media; using GT = Gadgeteer; using GTM = Gadgeteer.Modules; using Gadgeteer.Modules.GHIElectronics; using Gadgeteer.Modules.IntegralDesign; namespace TestLightSensor { public partial class Program { void ProgramStarted() { lightSensor.LightSensorHigh += new GTM.IntegralDesign.LightSensor.LightSensorEventHandler(lightSensor_LightSensorHigh); lightSensor.LightSensorLow += new GTM.IntegralDesign.LightSensor.LightSensorEventHandler(lightSensor_LightSensorLow); Debug.Print("Program Started"); } void lightSensor_LightSensorLow(GTM.IntegralDesign.LightSensor sender, GTM.IntegralDesign.LightSensor.LightSensorState state) { led.TurnOff(); } void lightSensor_LightSensorHigh(GTM.IntegralDesign.LightSensor sender, GTM.IntegralDesign.LightSensor.LightSensorState state) { led.BlinkRepeatedly(GT.Color.Red); } } }