Jeroen Swart

.NET Architect

Netduino - Getting Started with LCD

If you want to show more output then blinking LED’s, an LCD module is a good and usually affordable option. They come in different sizes, from 2 numeric-only digits to 40x4 alphanumeric dot-matrix modules. You can also get graphic LCD’s, that range from modules with small resolutions (e.g. 122x32 or 240x128 pixels) to more professional LCD screens (e.g. 5” or 7”),  but I will stick with alphanumeric LCD’s for this post.

Most alphanumeric LCD modules are built around a HD44780 or compatible controller, so they all use the same interface. They are controlled using an 8-bit parallel port, some pins for handshaking (controlling the transfer of data over the parallel port), pins for controlling the contrast and backlight if available and of course pins for power and ground. The parallel port can also be used in 4-bits mode, sending the 8-bit data in two write actions. This saves I/O ports, but takes more time to update the LCD.

There is an excellent library available on codeplex (with a good introduction on the blog of the author) for controlling LCD modules. This library makes showing text on a display as easy as calling a Write method with the desired string. It uses a provider-pattern to allow for different connection scenarios, like direct on GPIO pins, using a shift-register or using an I2C expander. And if you want to use another scenario, you can add your own provider.

I have a 20x2 LCD module that I connected directly to the GPIO pins of my Netduino using the parallel port in 4-bit mode. The connections are made on a breadboard, because this makes it a little easier to put all the wires together. Below is an image of the result. The sample code provided with the library contains a link to a very helpful schematic on the Arduino website. Remember to connect the power on the LCD module to the 5V of the Netduino. 3.3V is not enough and will leave the LCD blank.

 The library contains a simple example of how to use the library. It initializes the LCD, shows the obligatory “Hello world” and then enters a loop that shows the milliseconds since reset. Since I use the GPIO pins directly, I changed the provider in the example. The code I used is shown below.

public class Program
{
    public static void Main()
    {
        // create the transfer provider, use direct GPIO provider
        // Initialize the library with the numbers of the interface pins
        // Use wiring shown here http://arduino.cc/en/uploads/Tutorial/lcd_schem.png
        var lcdProvider = new GpioLcdTransferProvider(Pins.GPIO_PIN_D12,    // RS
                                                        Pins.GPIO_PIN_D11,    // ENABLE
                                                        Pins.GPIO_PIN_D5,     // D4
                                                        Pins.GPIO_PIN_D4,     // D5
                                                        Pins.GPIO_PIN_D3,     // D6
                                                        Pins.GPIO_PIN_D2);    // D7

        // create the LCD interface
        var lcd = new Lcd(lcdProvider);

        // set up the LCD's number of columns and rows: 
        lcd.Begin(20, 2);

        // print a message to the LCD.
        lcd.Write("Hello world!");

        while (true)
        {
            // set the cursor to the first column on the second line
            lcd.SetCursorPosition(0, 1);

            // print the number of milliseconds since reset:
            lcd.Write((Utility.GetMachineTime().Ticks / 10000).ToString());

            Thread.Sleep(100);
        }
    }
}

 

Netduino - Getting Started with steppermotors, shieldless

In my previous post, I explained how I used the Adafruit motorshield to control a steppermotor. Since this shield uses a shift register, it needs a lot of I/O-actions. To control the steppermotor without a shift register, I put together part of the motorshield schematic on a breadboard. What remains is a single L293D with a few supporting parts, as shown in the schematic below.

You can put the schematic together on a small breadboard. Connect D0, D1, D2 and D3 to the corresponding ports on the Netduino. Connect all grounds to the ground on the Netduino, all the VCC to the Netduino 3.3V and the Vin to the Vin of the Netduino. The power of the adapter will be on Vin, powering the motor. The image below shows my result.

I changed the library for the motorshield, used in my previous post, to work with the schematic above. You can download it here. The library only supports steppermotors and it only provides support for single, double and interleave step-types. Pins D0 - D3 are used by default, but you can use any of the digital I/O pins by providing them to the constructor of the Stepper class.

The sample program that comes with the library download does the same as the sample program in my previous post: it initializes a stepper motor with 200 steps per revolution (or 1.8 degrees per step) and then repeats a few forward and reverse 360 degree rotations for each supported step-type. An example of initializing the motor and moving it forward is shown below.

Stepper stepper = new Stepper(StepperPorts.M3_M4, 200);
stepper.Step(200, MotorDirection.Forward, StepType.Single);

But… does it increase the speed of the motor? Well, yes and no. For one motor it does, and for another it doesn’t. The first motor I tested (200 steps per rotation; the one in the image above) runs at 1.36 rotations per second using the shield and at 2.46 rotations per second without the shield, so using the direct control almost doubles the speed. The second motor (a small one with 48 steps per rotation) runs at 5.68 rotations per second with the shield and at 4.04 rotations per second without it, so slowing the motor down by almost 30%.

Of course, the measurements are hardly scientific, and I only tested two motors. I ran each motor for 10 full rotations and recorded the time that took. I did this 10 times for each step-type and calculated the averages.

However, there are some issues with this approach at the moment. Running the step-loop at the highest speed doesn’t move either motor one bit or they just shake somewhat. I had to put in a minimum wait-time of 1 msec after each step to get the motors to rotate. Another problem is the decrease in torque. I need to take a good look at the pulses that come out of the output-pins. Each part of the H-bridge is now controlled one after the other, instead of all at the same time (by setting up all the right output levels first, then providing them to the H-bridge all at once). I want to have a look at this, as soon as I can get my hands on an oscilloscope :-).

It’s not really the result I was hoping for. I’m looking for a speed of about 50 rotations per second. I’m planning to use NEMA 34 motors, which can do that easily. I’m not yet sure what’s causing the issues, but I do know that controlling the pulses directly with the microcontroller will not get me the high speed I’m looking for. One solution could be the use of an L297 chip. This is a steppermotor controller that turns two signals, a clock pulse (e.g. generated with PWM) and a direction signal, into the correct pulses for the H-bridge.

Next: working with LCD.

Netduino - Getting Started with steppermotors

Working with steppermotors is a bit more complex then working with regular DC motors. Apply a voltage to a DC motor and it will rotate. With stepper motors, you need to apply that voltage in a specific pattern.

Instead of using a single coil, as in a DC motor, most steppermotors use two coils. The number of steps is determined by the number of magnetic poles on the rotor. Two common types of steppermotors are unipolar and bipolar steppermotors.

Bipolar & unipolar

A bipolar steppermotor is controlled by reversing the polarity of each coil in the right order. A more detailed description of how a bipolar steppermotor works can be found here.

In a unipolar steppermotor the two coils each have a wire connected to their center. It is controlled by providing power between the center and one of the ends. The center of the coils is always connected to ground. Applying a positive voltage to one or the other end of a coil has the same effect as reversing the voltage on a coil in a bipolar motor. A more detailed description of unipolar steppermotors can be found here.

Wikipedia provides a nice article on steppermotors, which also shows an animation of a steppermotor.

The picture below shows some steppermotors. These are all unipolar. The left and right motors are the same type.

Below are two more pictures of the insides of the steppermotor.

   

Hardware

Since it takes some power to control motors, microcontrollers normally can’t control motors directly. Transistors are up for this job, as I explained before. To be able to provide some extra power, darlington transistors are often used with motors instead of single transistors. A darlington transistor is a set of two transistors that function as one, but can provide a much higher current gain than each transistor by themselves. The image below shows the symbol of a darlington transistor. You can read more information about them on Wikipedia.

Steppermotors are controlled by applying voltage to the ends of each coil (the center taps of a unipolar steppermotor are connected to ground), so you’ll need four (darlington) transistors. Such a set of transistors is called an H-bridge. You can make an H-bridge yourself or you can use an H-bridge chip. There are a lot of H-bridge chips available, like the L293D (handles 600mA), the L298 (handles up to 4A) or the ULN2004 (handles 500mA) to name a few.

Of course, you can also pick one of the motor shields available from stores like Adafruit or Sparkfun. I started with the motorshield from Adafruit. It consists of two L293D’s and can control 2 steppermotors (or 4 DC motors). It uses a serial/parallel shift register (74HC595N) to control the L293D’s with the least amount of I/O pins from the microcontroller. This is a nifty trick, although it makes the software a little bit more complex. It also takes more time to control the L293D’s. Each bit of the shift register (8 in total) must be set on a single data-pin and each data-bit is moved into the shift register using a pulse from a clock-pin; finally the result is made available on the parallel outputs of the register using a latch-pin, resulting in a total of 25 I/O-actions. This does not have to be a bad thing, but it does take more time and therefore limits the maximum speed of the motor.

The image below shows the motorshield, stacked on a Netduino, with a stepper motor connected. Since the USB connection can’t provide the power, I'm using an external power adapter.

Software

Adafruit provides an Arduino library for the motorshield. I found a Micro .NET port of this library on the Netduino forums, but it wasn’t working properly. You can download my version here. The microstep step-type (see below) still isn’t working, my motor just wiggles. I don’t think I’ll need microstepping myself, so I’m not really in a hurry to get it working :-). If you do need it, let me know and I’ll be glad to help. I also haven’t tested the DC motor part of the library.

The library provides four types of step-behavior: single, double, interleave and microstep. The single step-type activates a single coil at a time; this is also referred to as ‘wave drive’. The double step-type activates both coils at the same time; also referred to as ‘full step drive’. Double stepping uses twice the power and provides more torque, although not twice the torque. The interleave step-type combines both the single and the double step-type, activating one coil, then two coils, then one coil again and so on; this is also referred to as ‘half stepping’. Since each activation only makes a half step, this step-type requires twice the amount of steps to make the same rotation as the single or double step-type. The microstep step-type uses PWM (explained here) to have a finer control over the power supplied to the coils. Instead of simply switching a coil on or off, microstepping provides a sine waveform to each coil. This provides smoother rotation, but reduces the accuracy of the steps. As I mentioned, it’s currently not working in the library.

The sample program in the solution initializes a stepper motor with 200 steps per revolution (or 1.8 degrees per step) and then repeats a few forward and reverse 360 degree rotations for each (working) step-type. Below is a short example of how to initialize a motor and move it forward.

Stepper stepper = new Stepper(StepperPorts.M3_M4, 200);
stepper.Step(200, MotorDirection.Forward, StepType.Single);

I feel the shift register is limiting the speed of the steppermotor too much. So next, I will try to control the H-bridge directly, without the shift register.

Next: working with steppermotors, without the shield.

NetDuino - Getting Started with SD

The Netduino Plus has an on-board SD-card slot. It is connected to one of the SPI ports of the microcontroller. Fortunately, you don't need to write code to control the SPI port yourself. The firmware handles this for you, so all you need to do is work with the classes from the System.IO namespace. Do remember that this is the Micro .NET framework and it is not as rich as the full .NET framework, but it does provide enough implementation for working with the SD card.

The root of the file system on the SD card is '\SD'. So, to get all the files in the root directory, you could do the following:

[code:c#;ln:off;alt:on]string[] fileNames = Directory.GetFiles(@"\SD");[/code]

And anything else is just as simple as that. Below is an example that shows all folders and files on the card. You'll need to add a using statement for the System.IO namespace.

[code:c#;ln:off;alt:on]public class Program
{
    public static void Main()
    {
        DirectoryInfo rootDirectory = new DirectoryInfo(@"\SD\");

        RecurseFolders(rootDirectory);
    }

    private static void RecurseFolders(DirectoryInfo directory)
    {
        if (directory.Exists)
        {
            Debug.Print(directory.FullName);

            foreach (FileInfo file in directory.GetFiles())
            {
                Debug.Print(file.FullName);
            }

            foreach (DirectoryInfo subDirectory in directory.GetDirectories())
            {
                RecurseFolders(subDirectory);
            }
        }
    }
}
[/code]

If there is no card in the SD slot, the \'SD' directory will not exist. So check the Exist property before using the rest of the DirectoryInfo object. Using the object (other than the Exist property) if the directory it represents does not exist will throw an expection. If a DirectoryInfo object was already created, for an existing directory, and then the SD card is removed, an exception is thrown when accessing the object. Since removing a card is easy, you should write code that handles that possibility.

Oh, and do remember that the maximum SD card size the Netduino Plus can handle is 2GB. It is clearly mentioned on the Netduino Plus specifications page, but I overlooked it at first myself. When using a larger SD card, it will look as if no card has been inserted at all.

Next: communicate using RS232.

NetDuino - Getting Started with I2C

I2C is a serial communication protocol, used for communication between IC's. It uses two wires: one for data (SDA) and one for a clock signal (SCL). For more details on this protocol, check this Wikipedia article.

The Netduino has one I2C port which is available on pin A4 (SDA) and A5 (SCL). The I2C protocol works as a bus, so you can connect more than one slave devices to the one I2C port of the Netduino. For the I2C bus to work properly, you need to add two pull-up resistors to pins A4 and A5, regardless of the number of devices connected to the bus.

For experimenting with I2C, I’m using two ‘plugs’ that I got from JeeLabs a while ago. A plug is a small board that is easily plugged into a JeeNode (an Arduino-compatible board). There are several plugs available, like an Analog Plug, a DC Motor Plug or a Gravity Plug. I have an I/O Expander Plug and a RTC Plug, which I will use in the code below. Most plugs only contain a single I2C chip and a few supporting components. So putting one (or more) I2C chips on a breadboard should be pretty easy.

For the examples, I created some classes that represent the I2C plugs: a I2CPlug base-class, an ExpanderPlug class and a RTCPlug class. All three classes are shown below. Add them to your project to be able to use the examples that follow.

public class I2CPlug
{
    private const int DefaultClockRate = 400;
    private const int TransactionTimeout = 1000;

    private I2CDevice.Configuration i2cConfig;
    private I2CDevice i2cDevice;

    public byte Address { get; private set; }

    public I2CPlug(byte address, int clockRateKhz)
    {
        this.Address = address;
        this.i2cConfig = new I2CDevice.Configuration(this.Address, clockRateKhz);
        this.i2cDevice = new I2CDevice(this.i2cConfig);
    }
    public I2CPlug(byte address)
        : this(address, DefaultClockRate)
    {
    }

    private void Write(byte[] writeBuffer)
    {
        // create a write transaction containing the bytes to be written to the device
        I2CDevice.I2CTransaction[] writeTransaction = new I2CDevice.I2CTransaction[]
        {
            I2CDevice.CreateWriteTransaction(writeBuffer)
        };

        // write the data to the device
        int written = this.i2cDevice.Execute(writeTransaction, TransactionTimeout);

        while (written < writeBuffer.Length)
        {
            byte[] newBuffer = new byte[writeBuffer.Length - written];
            Array.Copy(writeBuffer, written, newBuffer, 0, newBuffer.Length);

            writeTransaction = new I2CDevice.I2CTransaction[]
            {
                I2CDevice.CreateWriteTransaction(newBuffer)
            };

            written += this.i2cDevice.Execute(writeTransaction, TransactionTimeout);
        }

        // make sure the data was sent
        if (written != writeBuffer.Length)
        {
            throw new Exception("Could not write to device.");
        }
    }
    private void Read(byte[] readBuffer)
    {
        // create a read transaction
        I2CDevice.I2CTransaction[] readTransaction = new I2CDevice.I2CTransaction[]
        {
            I2CDevice.CreateReadTransaction(readBuffer)
        };

        // read data from the device
        int read = this.i2cDevice.Execute(readTransaction, TransactionTimeout);

        // make sure the data was read
        if (read != readBuffer.Length)
        {
            throw new Exception("Could not read from device.");
        }
    }

    protected void WriteToRegister(byte register, byte value)
    {
        this.Write(new byte[] { register, value });
    }
    protected void WriteToRegister(byte register, byte[] values)
    {
        // create a single buffer, so register and values can be send in a single transaction
        byte[] writeBuffer = new byte[values.Length + 1];
        writeBuffer[0] = register;
        Array.Copy(values, 0, writeBuffer, 1, values.Length);

        this.Write(writeBuffer);
    }
    protected void ReadFromRegister(byte register, byte[] readBuffer)
    {
        this.Write(new byte[] { register });          
        this.Read(readBuffer);
    }
}
public class ExpanderPlug : I2CPlug
{
    private const int ExpanderPlugAddress = 0x20;

    public enum Registers
    {
        IODIR,
        IPOL,
        GPINTEN,
        DEFVAL,
        INTCON,
        IOCON,
        GPPU,
        INTF,
        INTCAP,
        GPIO,
        OLAT
    };

    public ExpanderPlug()
        : base(ExpanderPlugAddress)
    {
    }
    public ExpanderPlug(byte directions)
        : base(ExpanderPlugAddress)
    {
        SetDirections(directions);
    }

    public void SetDirections(byte directions)
    {
        this.WriteToRegister((byte)Registers.IODIR, directions);
    }

    public void Write(byte values)
    {
        this.WriteToRegister((byte)Registers.GPIO, values);
    }

    public byte Read()
    {
        byte[] values = new byte[1] { 0};

        this.ReadFromRegister((byte)Registers.GPIO, values);

        return values[0];
    }
}
public class RtcPlug : I2CPlug
{
    private const int RtcClockPlugAddress = 0x68;

    public RtcPlug()
        : base(RtcClockPlugAddress)
    {
    }

    public void Write(DateTime value)
    {
        byte[] dateBuffer = new byte[]
        {
            ConvertBinaryToBCD(value.Second),
            ConvertBinaryToBCD(value.Minute),
            ConvertBinaryToBCD(value.Hour),
            ConvertBinaryToBCD(0),
            ConvertBinaryToBCD(value.Day),
            ConvertBinaryToBCD(value.Month),
            ConvertBinaryToBCD(value.Year - 2000)
        };

        this.WriteToRegister(0, dateBuffer);
    }
    public DateTime Read()
    {
        byte[] dateBuffer = new byte[7];

        this.ReadFromRegister(0, dateBuffer);

        return new DateTime(ConvertBCDToBinary(dateBuffer[6]) + 2000,
                            ConvertBCDToBinary(dateBuffer[5]),
                            ConvertBCDToBinary(dateBuffer[4]),
                            ConvertBCDToBinary(dateBuffer[2]),
                            ConvertBCDToBinary(dateBuffer[1]),
                            ConvertBCDToBinary(dateBuffer[0]));
    }

    private static byte ConvertBinaryToBCD(int value)
    {
        return (byte)(value + 6 * (value / 10));
    }

    private static int ConvertBCDToBinary(byte value)
    {
        return value - 6 * (value >> 4);
    }
}

As a first example, we’ll toggle all the pins of the expander plug like the blink example.

public class Program
{
    public static void Main()
    {
        // initialize the expander plug, setting all pins as output
        ExpanderPlug expanderPlug = new ExpanderPlug(0x00);

        // do forever...
        while (true)
        {
            expanderPlug.Write(0xff);       // turn all the pins on
            Thread.Sleep(250);              // make the pins stay on for 250 ms
            expanderPlug.Write(0x00);       // turn all the pins off
            Thread.Sleep(250);              // make the pins stay off for 250 ms
        }
    }
}

You can use a LED (with a resistor in series) to test the level of each port as shown below.

Next, we’ll configure all pins as input. You can connect any pin to 3.3V using a resistor and see how the value changes. For the most stable results, connect all the input pins to ground if not connected to 3.3V.

public class Program
{
    public static void Main()
    {
        // initialize the expander plug, setting all pins as input
        ExpanderPlug expanderPlug = new ExpanderPlug(0xff);

        // do forever...
        while (true)
        {
            byte value = expanderPlug.Read();       // get the values of all the pins
            
            Debug.Print("value: " + value.ToString());

            Thread.Sleep(250);
        }
    }
}

For the final example I connected the RTC plug. A date is first written, then continouosly retrieved to show that the clock is running.

public class Program
{
    public static void Main()
    {
        // initialize the RTC plug
        RtcPlug rtcPlug = new RtcPlug();

        // write the current date/time to the clock
        DateTime now = new DateTime(2011, 7, 31, 15, 58, 0);
        rtcPlug.Write(now);

        Debug.Print("now: " + now.ToString());

        // do forever...
        while (true)
        {
            // read the current date/time from the clock
            DateTime value = rtcPlug.Read();

            Debug.Print("value: " + value.ToString());

            Thread.Sleep(250);
        }
    }
}

The Micro .NET Framework does have an internal clock and DateTime.Now does work, but it is reset to '01-01-2009 00:00:00' every time you restart the device. Since the Netduino doesn't have an on-board RTC, it doesn't know the actual date/time. You could use an RTC as shown above and change the current date/time by calling Utility.SetLocalTime once during the initialization of your program. If you really want to get the actual date/time (from an RTC) when calling DateTime.Now, you'll need to update the firmware.

Next: working with steppermotors.

NetDuino - Getting Started with RS232

A common communication protocol is RS232. This is a serial protocol, which uses two wires to transmit data in both directions one bit at a time. A port using this protocol is usually simply called a serial port, because it’s one of the most commonly used protocols for serial communication.

Connecting two devices using RS232 can be as simple as connecting 3 wires between them: transmitted data (TxD), received data (RxD) and ground. It is also possible to connect up to 6 more wires, which handle the handshake part of the RS232 protocol. Handshaking is used to synchronize the communication between the devices: e.g. to let the other device know data was sent or it’s ready to receive data. With 3 wires, and no handshaking, both sides must agree upon the details of the communication: the speed and the number of data-, start- and stop-bits.

What makes using the RS232 protocol difficult in standard digital electronics, is that the protocol uses different voltage levels. Instead of using 0V for a low level or ‘0’ and using the supply voltage (3.3V or 5V) for a high level or ‘1’, the RS232 protocol uses +3V to +15V to signal a ‘0’ and -3V to -15V to signal a ‘1’.

The conversion of RS232 signals and voltage levels is such a common task, that special chips (like the MAX232 or MAX3232) are available to handle this. They even make -12V and +12V out of a 5V or 3.3V power supply. Another option is to use a USB to RS232 converter, like the FT232 chip. This chip presents itself (at its USB side) as a USB serial port to your PC, which is recognized by Windows and a driver is automatically installed. You then have a virtual serial port (usually COM3 or higher) which you can use as if it was a regular RS232 serial port. Whatever you send to this virtual serial port will be present on the RS232 side of the FT232 chip, in logical 0’s and 1’s, and vice versa.

When connecting two microcontroller devices (e.g. two Netduino’s or a Netduino with an Arduino), there is no need to translate the signals. The appropriate ports of each microcontroller can simply be connected directly, or through any type of connector.

Another important thing to know is that the protocol was originally designed for computers and device communication. In this configuration the computer transmits over the TxD line and the device listens to the same line. When connecting two computers, or microcontrollers, to communicate with RS232, both are transmitting over the TxD line and listening on the RxD line. Therefore the lines must be connected across: TxD to RxD and RxD to TxD. When using the ‘real’ RS232 protocol, you can use a special null modem cable, where the TxD and RxD lines are crossed inside. When connecting without such a cable, e.g. between microcontrollers, just remember to connect TxD on one to RxD on the other.

If you want to know more about RS232, check out this Wikipedia article.

The microcontroller on the Netduino has 2 serial ports and both are available through the Netduino headers. Because my laptop has no serial port, I’m using a ‘USB BUB’ board. It’s nothing more than a simple board with a RL232 chip and some supporting components. It’s made by Modern Device, but I ordered mine from JeeLabs, together with some JeeNodes (an Arduino-compatible board).

To setup the hardware part of the example, connect the USB BUB to a PC with a USB cable. It will automatically install the necessary driver and show up as a USB Serial Port in the device manager as shown below.

The ‘LOGIC LVL’ jumper on the USB BUB should be in the 3.3V position, since that’s what the Netduino is working with, but 5V will also work. Connecting the Netduino to the USB BUB takes 3 wires as shown in the picture below. The black wire connects the ground of both boards. The green wire connects the RxD of the Netduino (D0) to the TxD of the USB BUB. The white wire connects the TxD of the Netduino (D1) to the RxD of the USB BUB.

The D0 (RxD) & D1 (TxD) pins of the Netduino headers are connected to the first serial port of the microcontroller, or COM1 for Micro .NET as we will see in code. The second serial port, or COM2, is connected to D2 (RxD) and D3 (TxD) of the Netduino. The first serial port doesn’t provide handshaking. The second serial port does provides handshaking (using CTS & RTS only), but you’re not required to use it.

Below is the code for the Netduino. It sets up a serial port to use COM1 and adds an event handler for when data is received. When data is received, a single byte is read and send back as long as there is data in the buffer to read. You need to add a using statement for the System.IO.Ports namespace. If you want to use COM2 instead, connect the USB BUB to D2 & D3 instead of D0 & D1 and change SerialPorts.COM1 in the code below to SerialPorts.COM2.

public class Program
{
    static SerialPort serial;

    public static void Main()
    {
        // initialize the serial port for COM1 (using D0 & D1)
        serial = new SerialPort(SerialPorts.COM1, 9600, Parity.None, 8, StopBits.One);
        // open the serial-port, so we can send & receive data
        serial.Open();
        // add an event-handler for handling incoming data
        serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);

        // wait forever...
        Thread.Sleep(Timeout.Infinite);
    }

    static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // create a single byte array
        byte[] bytes = new byte[1];

        // as long as there is data waiting to be read
        while (serial.BytesToRead > 0)
        {
            // read a single byte
            serial.Read(bytes, 0, bytes.Length);
            // send the same byte back
            serial.Write(bytes, 0, bytes.Length);
        }
    }
}

Next is the code for a simple console application. It uses COM3 which you might need to change depending on what your USB BUB is connected as; check your device manager. The application lets you type a string and sends it out. When data is received, it is shown. As with the Netduino code, you need to add a using statement for the System.IO.Ports namespace.

class Program
{
    static SerialPort serial;

    static void Main(string[] args)
    {
        // provide some usage information
        System.Console.WriteLine("enter some text and hit ENTER.");
        System.Console.WriteLine("enter 'x' and hit ENTER to exit.");
        System.Console.WriteLine();

        // initialize the serial port for COM3 (could be other port, depends on system)
        serial = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        // open the serial-port, so we can send & receive data
        serial.Open();
        // add an event-handler for handling incoming data
        serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);

        // this will hold each line entered
        string line = string.Empty;

        // as long as an x is not entered
        while (line.ToLowerInvariant() != "x")
        {
            // read a single line from the console
            line = System.Console.ReadLine();

            // convert the line to bytes
            byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(line);

            // send the bytes over the serial-port
            serial.Write(utf8Bytes, 0, utf8Bytes.Length);
        }
    }

    static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // wait a little for the buffer to fill
        System.Threading.Thread.Sleep(100);

        // create an array for the incoming bytes
        byte[] bytes = new byte[serial.BytesToRead];
        // read the bytes
        serial.Read(bytes, 0, bytes.Length);
        // convert the bytes into a string
        string line = System.Text.Encoding.UTF8.GetString(bytes);

        // write the received bytes, as a string, to the console
        System.Console.WriteLine("echo: " + line);
        System.Console.WriteLine();
    }
}

Notice how the code for initializing the serial port, sending & receiving data and even for converting of bytes to a string and back, is exactly the same for both platforms! How cool is that.

Next: working with I2C.

NetDuino - Getting Started with SD

The Netduino Plus has an on-board SD-card slot. It is connected to one of the SPI ports of the microcontroller. Fortunately, you don't need to write code to control the SPI port yourself. The firmware handles this for you, so all you need to do is work with the classes from the System.IO namespace. Do remember that this is the Micro .NET framework and it is not as rich as the full .NET framework, but it does provide enough implementation for working with the SD card.

The root of the file system on the SD card is '\SD'. So, to get all the files in the root directory, you could do the following:

string[] fileNames = Directory.GetFiles(@"\SD");

And anything else is just as simple as that. Below is an example that shows all folders and files on the card. You'll need to add a using statement for the System.IO namespace to your code and a reference to the System.IO.dll to your project.

public class Program
{
    public static void Main()
    {
        DirectoryInfo rootDirectory = new DirectoryInfo(@"\SD\");
        RecurseFolders(rootDirectory);
    }

    private static void RecurseFolders(DirectoryInfo directory)
    {
        if (directory.Exists)
        {
            Debug.Print(directory.FullName);

            foreach (FileInfo file in directory.GetFiles())
            {
                Debug.Print(file.FullName);
            }

            foreach (DirectoryInfo subDirectory in directory.GetDirectories())
            {
                RecurseFolders(subDirectory);
            }
        }
    }
}

If there is no card in the SD slot, the \'SD' directory will not exist. So check the Exist property before using the rest of the DirectoryInfo object. Using the object (other than the Exist property) if the directory it represents does not exist will throw an expection. If a DirectoryInfo object was already created, for an existing directory, and then the SD card is removed, an exception is thrown when accessing the object. Since removing a card is easy, you should write code that handles that possibility.

Oh, and do remember that the maximum SD card size the Netduino Plus can handle is 2GB. It is clearly mentioned on the Netduino Plus specifications page, but I overlooked it at first myself. When using a larger SD card, it will look as if no card has been inserted at all.

Next: communicate using RS232.

NetDuino - Getting Started with ADC

The Netduino contains several ports (A0 - A5) that are capable of reading an analog signal and changing it into a digital representation of that signal. These ports can be used for digital I/O as well, but can individually be configured to use an internal ADC (Analog to Digital Converter).

The analog signal at the ADC port can come from different sources. It can come from a sensor, e.g. for measuring light or temperature, or it is simply taken from a variable resistor, that is changed by a user to select some value (e.g. the desired intensity of a dimmed light). The analog signal is a voltage between 0V and 3.3V. The ADC converts this voltage to a number between 0 and 1023, since the Netduino has 10-bits ADC’s. The number 0 represents 0V and 1023 represents Aref. The voltage level at any ADC port can be determined as follows:

float analogValue = (float)digitalValue * (3.3f/ 1023f)

In theory, you should divide by 1024, because there are that many steps. The maximum digital value of 1023 in that case represents a voltage between 3.2967 and 3.3V, but the formula would result in the lower value. In practice it is easier to divide by 1023, so a digital value of 1023 represents the full scale of 3,3V. And with ADC precision-errors and a Vref that's probably not exactly 3.3V, the result is pretty accurate.

The example uses port A0 and continuously reads the digital value and converts it to the actual voltage at the port using the previously mentioned formula. For this example connect a variable resistor to port A0 as shown below.

public class Program
{
    private const int MaximumValue = 1023;
    private const float AnalogReference = 3.3f;

    public static void Main()
    {
        // initialize one of the analog pins
        AnalogInput adcPort = new AnalogInput(Pins.GPIO_PIN_A0);

        // do forever...
        while (true)
        {
            // read a digital value from the ADC
            int digitalValue = adcPort.Read();

            // convert digital value to analog voltage value
            float analogValue = (float)digitalValue / MaximumValue * AnalogReference;

            // show the analog value in the output-window
            Debug.Print(analogValue.ToString());
        }
    }
}

If the default Aref value of 3.3V is not convenient, you can provide your own Aref at the corresponding pin of the Netduino headers. It must however be between 2.6V and 3.3V. To let the Netduino actually use the external Aref, you need to switch port 56 (on the board, but not available on the headers) to low:

OutputPort arefSelect = new OutputPort((Cpu.Pin)56, false);

To use the 3.3V again, switch port 56 to high:

OutputPort arefSelect = new OutputPort((Cpu.Pin)56, true);

Another way to convert the digital value of the ADC port to some meaningful value in code, is by using the SetRange method of the AnalogInput class. It allows you to set the minimum and maximum value returned by the Read method of the AnalogInput class. The conversion of the actual value to the range you have set is then done for you. In the example above we could have added the following line after the declaration of adcPort:

adcPort.SetRange(0, 3300);

The digitalValue can then be used as is, or divided by 100 to get the exact analog value:

float analogValue = (float)digitaValue / 100;

Since Aref can’t be higher than 3.3V, no analog signal higher than 3.3V can be measured by a port directly. Any signal above Aref is read as 1023 and, if considerably higher, may damage the port. To solve this, use a voltage divider using two resistors as shown below. The voltage at the port is Ain x R6 / (R5 + R6). The values of the resistors in the schematic allow for a 5V input to be measured as 3V by the port (5V * 18k / 30k = 3V). You can change the resistor values to accommodate any input voltage, e.g. change R2 to 120k to measure up to 23V. Note however that, when the input value is increased in this way, the accuracy of the value read from the ADC does decrease accordingly. Instead of 1024 steps of roughly 0.003V to reach 3.3V full scale, the ADC will do 1024 steps of roughly 0.022V to reach 23V full scale.

Another trick shown here is the use of a zener diode to protect a port. A zener diode will not allow a higher voltage to pass then the voltage that it was designed for. I won't go into the detailed workings of a zener diode, but effectively it protects the port from any voltage higher than the zener voltage.

Next: using the SD card.

NetDuino - Getting Started with PWM

PWM (or Pulse Width Modulation) is a technique that basically allows digital circuits to control analog circuits. One of the applications for this is to control the speed of a motor or, as I will show you in a second, the brightness of a LED.

A digital port is either on or off. This is very logical, but not very helpful when controlling an analog device like a motor. The speed of a motor is usually controlled by varying the voltage: if you set the voltage higher, more current will flow and the speed of the motor will increase.

With PWM, the digital port is switched on and off really fast. The effective voltage for analog (DC) use is the average of the on and off levels and depends on how fast the port is switched. The time the port has been switched both on and off is called the period, the time the port is on is called the pulse and the time the port is on, relative to the period, is called the duty-cycle and is expressed in percentage. By controlling the width of the pulse, you control the effective voltage on the output. Luckily, most microcontrollers have one or more PWM ports. You only need to set the period, pulse and/or duty-cycle, and the microcontroller takes care of the rest.


This image shows a PWM signal with a 50% duty-cycle. With a supply voltage of 3.3V, like on the Netduino, this will result in an average output of 1.65V.


This image shows a PWM signal with a 25% duty-cycle. This will result in an average output of 0.825V when using a supply voltage of 3.3V.

The Netduino has 4 ports that are capable of producing PWM signals: D5, D6, D9 and D10. The PWM class is used to control one of these ports. It provides two methods to configure the port. With the SetDutyCycle method, the duty-cycle is simply set as a percentage. Passing 0 sets the port off all the time, resulting in an effective 0V output. Passing 100 sets the port on all the time, resulting in an effective 3.3V output. Passing 50 results in an pulse that’s on during 50% of the period, resulting in a 1.65V output. The SetPulse method allows a little more control. The first argument is the length of the period and the second argument is the duration of the pulse, both in microseconds. So calling SetPulse(1000, 250), results in a pulse that starts every 1ms and lasts 0.25ms; the duty-cycle in this case is 25%.

In the simple example below, the LED is dimmed to a specific level. Since the on-board LED is not connected to a port that allows PWM, we need to connect a LED ourselves. This example will work with a LED & resistor connected directly as shown here, or using a transistor as shown here. The only difference is that you need to use one of the PWM ports. The code below is using port D5. Please note that for controlling anything other than a LED, you will need a transistor to provide a decent amount of current.

public class Program
{
    public static void Main()
    {
        // initialize one of the digital pins (that support PWM!) for PWM
        PWM pwm = new PWM(Pins.GPIO_PIN_D5);

        // set the duty-cycle to a specific value
        pwm.SetDutyCycle(50);

        // wait forever...
        Thread.Sleep(Timeout.Infinite);
    }
}

In the example below, the LED is dimmed repeatedly from totally off to totally on and back again. It uses the same port and components as in the previous example.

public class Program
{
    public static void Main()
    {
        // initialize one of the digital pins (that support PWM!) for PWM
        PWM pwm = new PWM(Pins.GPIO_PIN_D5);

        // we start with the LED off
        int dutyCycle = 0;
        // we start with making the LED brighter
        bool up = true;

        // do forever...
        while (true)
        {
            // if making the LED more bright
            if (up)
            {
                // increase duty-cycle
                dutyCycle++;

                // if we're at 100%, start making the LED less bright
                if (dutyCycle >= 100)
                {
                    up = false;
                }
            }
            else
            {
                // decrease duty-cycle
                dutyCycle--;

                // if we're at 0%, start making the LED more bright
                if (dutyCycle

Another application for PWM is controlling servos, as are used in remote controlled cars and small robots. In this case the duration of the pulse controls the angle of the servo. The period is 20ms and a pulse of 1.5ms (duty-cycle 7.5%) puts the servo in the center or zero position. A pulse of 1ms (duty-cycle 5%) turns the servo completely to one side and a pulse of 2ms (duty-cycle 10%) turns the servo completely to the other side.

Next: using the ADC.

NetDuino - Getting Started with transistors

Controlling a LED directly using a port is fine in most cases, because a LED only requires a small current that can be supplied by the Netduino. But when controlling components that require more current (like high-power LED’s, motors, relays, etc.) a transistor is needed. The transistor is controlled by a small current from the MCU and the transistor controls the heavy load. While transistors actually work as amplifiers, they can also be used as switches.

Transistors exist in a few main types, like bipolar (either NPN or PNP) or FET. For our purpose almost any popular bipolar transistor will work. For each main type, there are many different types to select from. Examples for NPN types are: BC547, BC548 or 2N222. Examples for PNP are: BC557, BC558 or 2N2907. I picked the BC547, a NPN type, and will use it in my example which will simply control a LED. You can use the source code from the blink example in the Netduino Getting Started document.

The schematic shows a LED, again with a resistor to restrict the current through the LED. They are connected to the collector of the transistor, while the emitter is connected to ground (or common or 0V). When the transistor is switched on, current will flow through the transistor from the collector to the emitter. This current will also flow through the resistor and LED, so the LED lights up. When the transistor is switched off, no current will flow and the LED remains off. Switching the transistor is controlled by a current through the base. The base is connected to a NetDuino port through a resistor. And yes, the resistor is there to restrict the current. Since the current is only needed to switch the transistor and not to light up the LED a small current will suffice. A high level (true) on the NetDuino port will cause a current at the base, which will switch the transistor on and the LED will light up.

The above is of course a simple (but working) example. Each specific transistor type (BC547, BC548, etc.) has its own specifications, although many can be used in a similar way or even as a replacement in a situation as simple as this.

Since the Netduino ports are at 3.3V, when set high and the base-emitter voltage is 0.7V (which is the case for most transistors), the voltage-span over the resistor is 2.6V. This gives a 0.5 mA current (I = V/R => 2.6V / 5.6KΩ = 0.46 mA) through the resistor and at the base.

A PNP transistor, like the BC557 below, can replace the BC547 in the schematic above. Although, because of the different behavior of the PNP transistor, the LED will be off when the port is high and the LED will be on when the port is low.

On a PNP transistor the collector is drawn with an arrow inwards. On a NPN transistor the arrow is outwards on the emitter.

Connecting the transistor

A transistor is almost always part of a larger circuit, as it is not much use by itself. The easiest way of putting such a circuit together with the Netduino is using a breadboard or a breadboard shield. If you want to know more about using a breadboard, there are lots of online breadboard tutorials.

To connect any transistor in the right way, you'll need to know which pin is which. The datasheet for the transistor of your choice will help you out. Just google/bing the type and 'datasheet'. Below is a part from the datasheet of the BC547.

 

Next: dimming a LED.