HD44780 LCD Module driver for Windows 10 IoT

This is my first post about Windows 10 IoT and small computers (embedded) after some experiences in the past with the .Net MicroFramework (Netduino, in essence).

I must say that this Windows 10 is finally a small masterpiece, or “everything you ever asked and none never responded you”. The programming way is easy but very flexible, although still many bricks are missing (in development).

The source code on GitHub

Here is a very simple experiment, a bit vintage, of driving a common alphanumeric LCD module (HD44780-based) with a Raspberry PI 2 and Windows 10 IoT.

WP_001158

The project isn’t anything new, but rather kinda “refresh” of another of mine where the Netduino board was used (see below). Someone of you may wonder “why” still using a so-old LCD module when several graphics are available on the market. Well, my first answer is: “why not?”. As said, this project hasn’t any specific purpose (although many of you may dig into their “miracles box” and pull out an “almost useless” LCD module). The aim is to test how hard is to drive something well known.

 

Some credits…

I can’t miss to mention Laurent Ellerbach, who gave me some inspiration (and motivation) on pursuing those hacking/funny activities.

 

The hardware.

All you need is very easy to find:

  • Raspberry PI2 (with Windows 10 IoT installed)
  • any suitable HD44780 LCD display module (mine is a 4×20)
  • 74HC595 shift-register
  • 220 Ohms resistor (only if you need the backlight)
  • 10k Ohms trimpot (22k or 47k are fine the same)

For sake of simplicity, I won’t detail how to set up the Raspberry, but there are many articles which describe very well that. I followed the Microsoft site and everything went fine, except for the suggested SD minimum size: I found that a 8GB won’t work. Simply consider a 16GB.

RPI2-HD44780_schem

RPI2-HD44780_bb

 

The software.

I wanted to publish the project keeping the sources simpler as possible. A similar application won’t have sense in a complex hardware (full-featured TFT displays and HDMI monitors perform way better than this module). The general guideline is: if you find convenient to connect a LCD module to a RPI, then make it working in minutes.

Since the LCD module’s capabilities are very limited, I embraced the idea to expose the APIs as it were a kind of “Console”. Just a “write” and something more, where a background task should manage the physical transfer by itself.

The project contains two different demo:

  1. a basic one, where some strings’ content is reflected on the display;
  2. a slightly more complex demo, which gets a bunch of RSS news from the BBC.uk channel, and rotates the titles on the screen.

 

Basic demo.

    class BasicDemo
    {

        public async Task RunAsync()
        {
            //write a static string
            DriverHD44780.Instance.DrawString(
                "This is a basic demo",
                new Point(0, 0)
                );

            int n = 0;
            while (true)
            {
                //display a simple counter
                DriverHD44780.Instance.DrawString(
                    $"Counting...{n}",
                    new Point(0, 1)
                    );

                //display current time and date
                var now = DateTime.Now;
                DriverHD44780.Instance.DrawString(
                    now.ToString("T") + "   ",
                    new Point(0, 2)
                    );

                DriverHD44780.Instance.DrawString(
                    now.ToString("M") + "   ",
                    new Point(0, 3)
                    );

                n++;
                await Task.Delay(1000);
            }
        }

    }

WP_001159

 

RSS demo.

    class RssDemo
    {

        public async Task RunAsync()
        {
            //write a static string
            DriverHD44780.Instance.DrawString(
                "Getting RSS...",
                new Point(0, 0)
                );

            //get the latest news using a normal HTTP GET request
            var http = new HttpClient();
            var endpoint = new Uri("http://feeds.bbci.co.uk/news/rss.xml");

            var srss = await http.GetStringAsync(endpoint);
            var xrss = XDocument.Parse(srss);

            //extract the news items, and sort them by date-time descending
            var xnews = xrss.Root
                .Element("channel")
                .Elements("item")
                .OrderByDescending(_ => (DateTime)_.Element("pubDate"))
                .ToList();

            int n = 0;
            while (true)
            {
                /**
                * Loop the news as one per page
                **/

                //the first row is for the publication date-time
                var dt = (DateTime)xnews[n].Element("pubDate");
                DriverHD44780.Instance.DrawString(
                    dt.ToString("g"),
                    new Point(0, 0)
                    );

                //the three other rows are for the title
                var title = (string)xnews[n].Element("title");
                title = title + new string(' ', 60);

                for (int row = 0; row < 3; row++)
                {
                    DriverHD44780.Instance.DrawString(
                        title.Substring(row * 20, 20),
                        new Point(0, row + 1)
                        );
                }

                //wait some seconds before flipping page
                n = (n + 1) % xnews.Count;
                await Task.Delay(3000);
            }
        }

    }

WP_001165

 

Performance.

You may wonder how well performs the driver. Well, there are two stages involved in the displaying process:

  1. the calls from the main application to the driver;
  2. the physical data transfer.

Any invokation by the main app involves always the cache: no matter how many calls are made, because everything is hosted in memory. For this reason, any manipulation is irrelevant in terms of performance impact. However, a fixed rate (typically 200ms) there’s a cache dump to the LCD screen, that is: the physical data transfer though the SPI.

How long takes the entire screen dump via SPI?

The circuit is very simple, thus there’s no way to take the transfer faster than the machine execution speed. Even adjusting the SPI clock rate, the resulting duration won’t change notably. Please, bear in mind that a too high SPI clock rate could face signal degradation due the wire length. I used a perfect 1 MHz value, and you can see from the below screenshot that the total transfer duration is less than 30ms.

UNIT0000

If you are interested in a faster way to dump the data via SPI, I suggest to read the following section which requires a decent knowledge about electronics.

 

The old “LCD Boost” library.

The original project was tailored for the .Net MicroFramework (Netduino) and many things were optimized for speed reasons. Moreover, the NetMF had some leaky problems mostly due to the super squeezed CLR, thus many solutions were solved as it were a low-level device.

Here are some links to the original articles of mine:

Very fast SPI-to-parallel interface for Netduino

LcdBoost library for Netduino

The GDI library for Netduino targets a LCD module.

A playable Invaders-like game with a Netduino Plus 2.

 

Netduino + FT800 Eve = MicroWPF

The spare time is few, but step by step the target is getting closer.
It’s a been I’ve started playing around the FTDI FT800 Eve board, and it must admit it is awesome. If you need a quick solution to add a small touch display to your *duino board, the Eve is something you should consider.

EVE image

You know, I love Netduino and C#. That’s because I chose to play with the display using Netduino (Plus 2), and honestly I’d expected a pretty bad performance. Instead, the graphic engine of the Eve can be easily driven via SPI from any board. That is, the SPI on Netduino is fast, very fast.

My goal is creating a small library for helping many users to create small and funny home/hobby projects with the Netduino and the Eve display boards. Since I love the classic WPF, how could I avoid to inspire from them?

Micro WPF

If you know WPF, many concepts would come easier. Otherwise, I recommend to take a look to the documentation, tutorials and whatever you want. Even if you don’t harm with a PC, rather with the Windows Store/Phone APIs, the approach here isn’t too far from.
The “WPF” term for a simple Netduino is clearly abused. Here is just the visual approach, the XAML-like approach to create the UI, and -yes- the same ability to create your own controls: MeasureOverride and ArrangeOverride.
That’s not all.
If you have any visual application in mind with Netduino+Eve (e.g. a climate control, IoT client, etc), then probably you’d need some kind of navigation service across several pages. That’s the most modern UI experience, on every device: PC, tablets, and phones.

I still don’t write what the library will offer, because it’s just something made for fun: for helping hobbists and even students working with a UI on a such small board as Netduino is.
For sure, there are NOT (nor in the future):

  • data binding
  • XAML parsing (the tree has to be created programmatically)
  • styling
  • the remaining 99.99% of regular WPF…

An example of layout

The most versatile yet complex layout control is the Grid, but it seems working fine.
Let’s take this sample XAML:

<Page x:Class="WpfApplication2.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
	Title="Page1">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <StackPanel
            Grid.Row="0"
            Grid.Column="0"
            x:Name="R0C0"
            Background="Blue"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="1"
            x:Name="R0C1"
            Background="DarkGreen"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="2"
            x:Name="R0C2"
            Background="Red"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B0"
                />
        </StackPanel>


        <StackPanel
            Grid.Row="1"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            x:Name="R1C0"
            Background="LightPink"
            />


        <StackPanel
            Grid.Row="2"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            x:Name="R2C1"
            Background="MediumSlateBlue"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B2"
                />
        </StackPanel>

    </Grid>
</Page>

On the regular WPF the result is the following:

sample-wpf

Now, let’s see how to write the same thing on Netduino:

    public class DemoPage2 : PageBase
    {
        protected override void OnCreate(FT800Device dc)
        {
            var btn_prev = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Prev" };
            btn_prev.Click += new EventHandler(btn_prev_Click);

            var btn_next = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Next" };
            btn_next.Click += new EventHandler(btn_next_Click);
            btn_next.HAlign = HorizontalAlignment.Center;

            var grid = new WidgetGridContainer();
            grid.Name = "GRID";

            grid.AddColumnDefinition(150);
            grid.AddColumnDefinition(1, GridUnitType.Star);
            grid.AddColumnDefinition(1, GridUnitType.Auto);

            grid.AddRowDefinition(1, GridUnitType.Star);
            grid.AddRowDefinition(2, GridUnitType.Star);
            grid.AddRowDefinition(1, GridUnitType.Auto);

            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C0";
                ctr.Background = Colors.Blue;
                grid.SetRowCol(ctr, 0, 0);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_prev);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C1";
                ctr.Background = Colors.DarkGreen;
                grid.SetRowCol(ctr, 0, 1);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C2";
                ctr.Background = Colors.Red;
                grid.SetRowCol(ctr, 0, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(
                    new WidgetButton() { Name = "B0", Margin = new Thickness(10, 5) }
                    );
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R1C0";
                ctr.Background = Colors.LightPink;
                grid.SetRowCol(ctr, 1, 0, 1, 2);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R2C1";
                ctr.Background = Colors.MediumSlateBlue;
                grid.SetRowCol(ctr, 2, 1, 1, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_next);
            }

            this.Content = grid;
        }

        void btn_prev_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.GoBack();
        }

        void btn_next_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.Navigate(new DemoPage3());
        }
    }

That leads the following snapshot:

My Snapshot5

NOTE: by live the display shows the colors correctly. However, the picture taken renders a bad result.

Widgets, widgets, widgets…

The Eve board is very well designed, because it’s plenty of useful widgets. I don’t believe you’d need something different from the provided.
At the moment of writing, the Netduino library supports:

  • (normal) Button
  • ToggleButton
  • TextBlock
  • Slider
  • Dial

and, as for the layout control:

  • StackPanel
  • Grid

As long the spare time helps me, I will try to add some other useful component as the TextBox and the Image.

Yet some screens generated by the Netduino and the FT800 Eve board.
WP_000595

My Snapshot4

My Snapshot3

My Snapshot7

Source code

I will release a beta release soon.

An example of an hardware problem and how to solve it

This post was not planned, in the sense that the main article is expected on the real working project (coming soon), not on the problems related. However, this is a typical case of hardware malfunction (due to a insufficient design redundancy), and it thought it was useful to show. I realized that most users not having a good practice in electronics, get discouraged when they try to replicate a circuit and that does not work as expected. They first wonder about the “logical equivalency” of the schematic/wiring, but that does not seem a good reason for make it working.
works-on-my-bb
Electronics is physics, I mean a small part of. So, the world is not working differently when we talk about electrons spinning or a logic chip connected to a micro-controller. However, the main task done for years by scientists is to simplify, to model, to minimize interaction between “electronic parts”, so that the design will become easier yet reliable.

Yesterday.

In this post I want to describe what happened to me yesterday, when I was trying to make the circuit working, but it did not wanted to. All my attention was payed on the software (written by me), on possible bugs in the new Netduino Plus 2, and even about some wrong wiring. None of these areas was the right one, but the most unsuspected component.

Image00003

The goal of the project is interfacing a Sure Electronics Led-matrix board to the Netduino Plus 2 with a minimal external hardware. By the way, the board can be SPI-driven with a couple more of signals. All I need is some pull-up resistor, just because the STM32 MCU used by the Netduino Plus 2 does not embed them as the Atmel does.
So far, so well.

Yesterday the C# software driver was completed and worked well…ehm, bad…or well?…Hard to say how…
According to the Sure Electronics datasheet, as well as the Holtek HT1632 datasheet, my driver running on the Netduino produced the waveform correctly. Every single pattern, command, and data have been checked on the scope, and looked fine. However, the leds on the board were not lighting at all, or -at most- randomly colorized.

Today.

I had a suspect on the board itself, but I refused it because I mumbled:

…these boards are sold worldwide in thousands units: how can be not working?

However, today I checked the board correctness against its schematic.
The first yet easy component to check was the mapper for enabling the HT1632 led-controllers. There are four controllers on my board, which is 16 rows by 32 columns, bi-color led-matrix. The mapper is a normal 74HC164 shift-register, similar but simpler than the famous 74HC595.
The software driver clocks the 74HC164 so that only one HT1632 is enabled at once. Basically the driver issues a logic “zero” to the shift-register input, then shifts once: this will move the zero to the first register output, while all the remaining are “one”. This enables only the first controller, and the driver feeds it with the matrix data. Every further clock should issue a logic “one”, so that the logic “zero” is “moving” forward on the register’s outputs, and the other controllers are enabled.

The 74HC164 used for enabling the led controllers.
The 74HC164 used for enabling the led controllers.

What made me shocking is the wrong output state of the register. Although the clocks were issued correctly, as well as the input data, the outputs were completely wrong, most of the times enabling more controllers at once. That was a very good reason for the leds lighting randomly!
So, my move was to inspect what made the shift-register shifting unexpectedly. To do that, I placed the first scope probe on the 74HC164 output activating badly, and the second probe on the same chip clock. At first glance there was no reason for the output getting low, because there was no clock edges. However, something must happen, because the 74HC164 actually shifts the data.
The 74HC164 clock (above) and its first output going low.
The 74HC164 clock (above) and the data input fed into.

The first output of the shift-register, which correctly goes low along a whole clock period.
The first output of the shift-register, which correctly goes low along a whole clock period.
The shifter's second output going low earlier than the second clock pulse.
The shifter’s second output going low earlier than the second clock pulse.
The clock generated by the Netduino is perfectly flat upon the output falling: that's suspect!
The clock generated by the Netduino is perfectly flat upon the output falling: that’s suspect!

The driver timings are around several milliseconds: even the new Netduino can’t reach microseconds pulses. By the way, the external logic does not care about milliseconds, and it works even on nanoseconds events.

The actual clock by the 74HC164 pin shows a small glitch shorter than 100nS.
The actual clock by the 74HC164 pin shows a small glitch shorter than 100nS.

I scaled the scope time-base up to sub-microseconds timings, and…GOTCHA!…a subtle pulse was causing the improper shifting.
Now, I didn’t know exactly where that pulse is originated, nor the very best way to avoid it. By the way, it had to cut off, otherwise the board won’t worked. Two guesses: stray capacitance (e.g. PCB tracking too tight), and/or bad grounding (e.g. leds’ current leads voltage drops).

The solution.

The easier way to cut a spike off is placing a small 1nF capacitor across the signal and ground (assuming the grounding is good).

The 1nF capacitor added to the board.
The 1nF capacitor added to the board.

The funny thing is that the capacitor was considered by design, but not mounted (at least on my board). I wonder why the Sure Electronics Engineers missed it.

The 74HC164 second output shows perfectly after the capacitor insertion.
The 74HC164 second output shows perfectly after the capacitor insertion.

Conclusions.

I know, it’s frustrating.
Most of the users having fun with Netduino are programmers, and they can’t accept that does not exist “copy-and-paste” for hardware. Well, it can be applied if the circuit model has enough redundancy so that most of the undesired effects and interactions can be ignored.
So, please, don’t trash your long awaited hardware project just because it does not work at first time. Dig, dig, and dig again. Also remember that a logic analyzer can’t replace a scope, but a scope most of the time can.

Led-matrix controller driven via SPI

Introduction.


Time ago, Stanislav -a Netduino community user- posted a problem on how to drive a 6-by-4 led-matrix using its Netduino. After some experiment, he got stuck with the circuit, because a matrix must be multiplexed, and that’s not easy to solve.
Here is the link to the forum thread.

 

If you read the message exchange on the thread, then you’ll collect easily a list of constraints. Here they are:

  • the leds have been already assembled (i.e. only the multiplex driver is needed)
  • the overall price should fall within 10 Euro
  • must be handcrafted, thus no use of small parts (e.g. SMDs)
  • the multiplex should not stop its cycling as the Netduino stops (avoid leds burnout)
  • the circuit should avoid complicate wiring, so that the PCB can get pretty easy
  • reliable enough
  • finally, Stanislav asked to learn how to design such a circuit

It was clear that Netduino only wasn’t enough to drive a 6×4 led-matrix. First off, for the inability to give enough current for the leds, and secondly for the relative slowness of the managed code running into.

 

The problem in depth.

Light up a led is very simple. Starting from the power supply, as parameter you have the current flowing through the led, then calculating the resistor to put in series. A led needs from few mA (SMDs), to several hundreds of mA (or even more) for the high-power class.
Let’s face the multiplex problem thinking to a normal discrete-led which needs 10 mA for a normal brightness.

So, what is a multiplex?
The multiplexing is a technique for driving many loads (e.g. leds), using a relatively low number of wires. Thinking to a 6×4 led-matrix, instead having 24 wires (one for each led), the multiplex-way needs only 6+4 = 10 wires at all. The trick is enabling one column at once, and issuing the related row pattern. If this process is fast enough, our eyes can’t perceive the scanning.
Now, let’s focus on a single column of four leds: the scan process cycles over, but each column is enabled only at 25% (i.e. 1/4) of the total cycle-time. It means that to yield the same brightness as the led was lit with 10 mA, we should raise it of a factor of 4, thus 40 mA. This current is off the upper limit achievable by a normal logic chip.
By the way 40 mA is probably above the led’s limit. However, the current is flowing only for a quarter of the cycle, so there’s no warm up in the *average*. We only should take care to *avoid* any cycle break, otherwise the 40 mA will flow for a too long time, and the led blows.
That’s not all. When a column is enabled, there are 6 leds composing it, and they might be all on (worst case). So, the total current flowing is 40 mA x 6 = 240 mA.
How much is the current of each row, instead? A row drives only the led at where the column is enabled, but at 25% duty, of course. It means the 40 mA seen above.

 

My solution.

To solve this problem, I see three ways:

  1. using any small micro-controller (e.g. AVR, STM8, etc), then creating a program for both multiplexing the matrix, and for communicating with the Netduino. However, this solution still has the current limitation problem, and easily could take the overall cost over 10 Euro.
  2. using an ASIC, such as the AS1108: this way probably keep the cost within the limit, but can’t get the current higher than the chip’s max-rating.
  3. creating the circuit in the “classic-way”, using simple logic gates that you can buy everywhere for fews Euro. This solution seems having only the fault on the low compactness. However, there are tricks to minimize the hardware, and the compactness didn’t seem a constraint.

My choice was for the third option, for several reasons: it’s easy to create, it teaches how to design a led-matrix driver, it’s also cheap. I’d add it’s also pretty flexible, because you could change some component upon the leds current. It’s even modular: can create (theoretically) as many rows and columns as you wish, by simply adding a stage.
I had an old 7×5 led-matrix display: not so good, IMHO. It requires about 10 mA to light a led, but the brightness isn’t so high. Even raising the current to 20-25 mA, there’s no significantly better shining. I have several modern leds, and they should fit much better a similar project, because with as little as 5 mA they shine a lot more than my matrix. However, I used it for a faster prototyping.
In my circuit I also reversed the rows/columns role, but that does not change anything about the concept. It’s only for my convenience.

 

How it works.

The circuit is based on the famous shift-register 74HC595. A single register holds one-column pattern, that is 7 leds. Since we can chain several shift-register, I chained 5 of them: one for each row. The software for loading via SPI a bit stream into the chained registers is trivial, but there are several libraries such as the Stefan’s “Bit-shift shizzle”.
The Netduino has only one task: shift the whole stream of bits into the five registers, by using the SPI.
Afterward, the trick is playing with the /OE input of each register: when this line is high, all the register’s outputs are completely “detached” from the circuit. That is, we can parallel all the outputs, and enable one register a time leveraging the /OE behavior.

NOTE: the circuit shows only three registers for clarity.

The /OE signals should be cycled. To do that, I used a simple clock generator (NE555), and a 4017 (or 74HC4017), which is a Johnson counter.
The NE555 generates a square-wave of about 500 Hz, which feeds the counter. The 4017 simply puts high one of its outputs at once: every clock edge the next output is pulled high, as a natural 10-sequence. This sequence is also used for the column’s cycle, because the registers enabling must be synchronized with the proper led-column activation. Since the matrix is composed by 5 columns, the 4017 sequence must be shorten to that quantity. To achieve this, simply wire the 6th output to the counter reset: as soon the sequence hits the 6th output, its logic high also resets the counter taking the first output high immediately.


Both the shift-registers circuit, and the sequencer requires no particular difficulty.
The complex section is the real leds driver, which has to amplify the current (possibly wasting almost no power).
There are two cases of led-matrix pattern: common-cathode or common-anode. To clarify, let’s take the columns as reference: either the column lines represent the leds’ cathode, or the leds’ anode instead.


My display is a common-cathode, and the Stanislav case is about a common-anode, instead.

 

The led driver for columns sharing the cathodes.

The following circuits targets the current amplification for both columns- and rows-lines.

NOTE: the circuit shows only few rows/cols for clarity.

The row signals are coming directly from the 74HC595 outputs, which aren’t powerful enough to drive the leds. Thus a PNP-transistor (I used BC640) for each row is used for amplifying the signal. The PNP is wired as common-emitter, so that the registers have to set the output low to activate the led-row.
The ultimate goal for these transistors is taking them to the saturation: that’s for minimizing the voltage drop across the emitter-collector. More voltage available for the leds, and lesser power waste on the transistor themselves.
Notice that I didn’t used any resistor in series to the transistors base. That’s because I wanted to maximize the current through the base, so that the saturation will be guaranteed. The register stress is relative, because -yes- the current is above the chip’s rating, but also that is for a short period in a cycle. We should always bear in mind the *average* behavior.

For the columns the amplification circuit is more complex.
That’s because every column transistor should saturate flowing a current of 350 mA (or more). It worth noting that my matrix is 7×5, so that the column current is 7 x 50 mA = 350 mA (see the above calculation).
The BC639 NPN-transistor is the dual of the BC640, and it’s rated up to 1 A (continuous). Its hFE (current amplification ratio) is rated at about 25 when the collector current is about 500 mA. That means a base current greater than 500 / 25 = 20 mA, to ensure the saturation. This value is very close to the upper limit achievable by the 74HC4017, and furthermore the drop C-E looks still pretty high. The BC639 specs indicate a VCE = 0.5V @ Ic=500 mA and Ib=50 mA. All that imply another stage for pre-amplification.
The pre-amplification stage is a common-collector pattern: simple, yet good for taking the current higher. Please, also notice that the transistor pair are NOT connected as Darlington. The Darlington fault is that you cannot take it to the saturation, and we want that instead.
I used a 1k Ohms resistor for the final-stage-base, which is fine for a column current up to 500 mA. However, you could take this value lower (e.g. 330 Ohms) whereas the required column current should be greater.

You know, this driver is designed for taking the columns to the ground in order to light the leds. So, when the 74HC4017 output is high (just one at once), the related transistor-pair stage shorts the column line to the ground.
But…remember? We also need to enable the related shift-register, so that the bits pattern will be issued against the rows. The same column signal is also used for activating the /OE of the 74HC595. Since when the column is not active there’s also nothing taking the /OE high, there’s an additional pullup (2.2k Ohms) to achieve that. However, the presence of this pullup doesn’t involve the matrix behavior in any way.

 

The led driver for columns sharing the anodes.

This is the case of Stanislav, and the circuit looks a little simpler than the above.


The considerations about the current flowing through the transistors are the same as before. The only difference is in the polarity, which has to be reversed.

 

Power supply.

NOTE: this section is very important. An improper wiring may lead to an unexpected or quirky behavior of the circuit.

There are three sections involved in the whole project: the Netduino, the logic (shift-registers and the sequencer), and the drivers (rows’ and columns’). All the grounding must be carefully shared: the logic can be powered from the Netduino +5V supply, but the driver can’t.
The drivers (i.e. the leds) need a lot of power, which must be supplied separately.
You should observe this pattern for supplying the various power sources:


The circuit should be created along two sections: the logic and the drivers.
The two grounds (Netduino’s and leds’ power) should be joined in the middle point between the two sections. So, the two current loops are kept separated.
As stated, the positive leads of the two supplies must be not connected together.

 

Modularity.

As stated in the beginning, the circuit is clearly modular.
The 74HC595 offers up to 8 outputs (i.e. rows), so you can add a transistor and a led strip with ease. Since the registers are already chained, it’s also not hard to double-chain them, and reach 16 rows or even more.
Pretty the same consideration for the columns: the 74HC4017 yields up to 10 outputs (i.e. columns). Just add a transistor-pair stage, and the leds.
In this case is a bit more difficult to expand the column outputs over ten, but it’s not impossible at all. I’ll avoid any description over here, unless explicitly requested.
Modularity yields a relatively easy wiring of the PCB, or any other concrete solution.

 

The prototype.

NOTE: the circuit scans the led-matrix automatically, also when the Netduino is halted or even detached. This should prevent over-current through the leds, and facilitates the debugging of the software application.

Here are some pictures about the prototype built over two (!) bread-boards.

The whole prototype seen from above.

 

Detail of the 5×7 led-matrix

 

Detail of the five shift-registers (74HC595) chained.

 

Detail of the clock generator, and the 74HC4017 (i.e. the column scanning)

 

Detail of the seven rows’ drivers (BC640)

 

Detail of the five columns’ drivers (2 x BC639)

 

The demo program.

Below is the source code used for the demo (see below). Nothing else is required.

    /// <summary>
    /// Sample application for testing the led-matrix driver
    /// </summary>
    /// <remarks>
    /// NOTE: it's important to bear in mind that the circuit
    /// uses a negative logic, thus a logic '1' means a led off.
    /// </remarks>
    public class Program
    {
        //define the bit-buffer as mirror to the 'HC595 chain
        private static byte[] _buffer = new byte[5];

        //define some bit-masks, just for improving speed
        private static int[] _mask0 = new int[8] { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
        private static int[] _mask1 = new int[8] { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };


        public static void Main()
        {
            //fill the whole buffer with logic '1' (turn all the leds off)
            for (int i = 0; i < 5; i++)
            {
                _buffer[i] = 0xFF;
            }

            //defines the first SPI slave device with pin #10 as SS
            var cfg595 = new SPI.Configuration(
                Pins.GPIO_PIN_D10, // SS-pin
                false,             // SS-pin active state
                0,                 // The setup time for the SS port
                0,                 // The hold time for the SS port
                false,             // The idle state of the clock
                true,              // The sampling clock edge (this must be "true" for the 74HC595)
                1000,              // The SPI clock rate in KHz
                SPI_Devices.SPI1   // The used SPI bus (refers to a MOSI MISO and SCLK pinset)
            );

            //open the SPI port
            using (var spi = new SPI(cfg595))
            {
                //set the initial ball's position
                var ball1 = new Point();
                ball1.X = 2;
                ball1.Y = 5;

                //set the initial ball's speed
                var speed1 = new Point();
                speed1.X = 1;
                speed1.Y = 1;

                //endless loop
                while (true)
                {
                    //clear the led where the ball now is
                    SetPixel(ref ball1, false);

                    //move the ball accordingly to its speed
                    ball1.X += speed1.X;
                    ball1.Y += speed1.Y;

                    //check for the display "walls"
                    //NOTE: it's a rect having width=5, and height=7
                    if (ball1.X > 4)
                    {
                        ball1.X = 4;
                        speed1.X = -1;
                    }
                    else if (ball1.X < 0)
                    {
                        ball1.X = 0;
                        speed1.X = 1;
                    }

                    if (ball1.Y > 6)
                    {
                        ball1.Y = 6;
                        speed1.Y = -1;
                    }
                    else if (ball1.Y < 0)
                    {
                        ball1.Y = 0;
                        speed1.Y = 1;
                    }

                    //light the led at the new ball's position
                    SetPixel(ref ball1, true);

                    //copy the bit-buffer to the 'HC595 chain
                    spi.Write(_buffer);

                    //wait a little
                    Thread.Sleep(120);
                }
            }

            //useless in this case, but better than missing it!
            Thread.Sleep(Timeout.Infinite);
        }


        /// <summary>
        /// Simple helper for setting the state of a pixel
        /// </summary>
        /// <param name="pt">The pixel coords</param>
        /// <param name="state">The desired led state (true=on)</param>
        /// <remarks>
        /// The "ref" yields better performance than
        /// passing two parameters (X,Y) separately
        /// </remarks>
        private static void SetPixel(
            ref Point pt, 
            bool state)
        {
            if (state)
            {
                //the led should be turned on,
                //then let's clear the related bit
                _buffer[pt.X] &= (byte)_mask0[pt.Y];
            }
            else
            {
                //the led should be turned off,
                //then let's set the related bit
                _buffer[pt.X] |= (byte)_mask1[pt.Y];
            }
        }

    }


    /// <summary>
    /// The basic point structure
    /// </summary>
    public struct Point
    {
        public int X;
        public int Y;
    }

Here is a short video demonstrating the circuit prototype.
The Netduino runs a small program for bouncing a ball.

Enjoy!

Effect of long wiring on digital signals

It’s a very common question from the Netduino users. It’s about how to connect two or more boards/shields when they are relatively far each other.

The appliances and the mains.

It’s perhaps the habit to take the mains everywhere simply adding a piece of chord: the vacuum-cleaner works. Or else, during Christmas, when we have to plug half a dozen of light strings to the mains. No matter how we plug the cables: the Christmas tree is shining. We’ve only to take care of: (1) ensure a good mains connection, and (2) take care to avoid any false-contact which may cause overheat.
By the way, everything is working fine for several reasons:

  • the voltage is high enough, so that any small voltage drop will be insignificant;
  • the waveform of the mains is a wonderful sine, swinging at a very low frequency (50 or 60Hz);
  • but, of sure, the most important fact is that:

there’s no any information carried over the mains wiring, thus our appliance will “understand” just “go/no go”.

The digital signals.

Working on digital logic, microcontrollers and else, we need mostly transfer “information” from a block to another one. This “information” can be a simple bit high/low, but it can be much more complex (e.g. the SPI). The higher is the quantity of information, the harder is to protect it from errors.
It’s the famous “signal-to-noise ratio“, which impose a limit to the maximum quantity of information over a line when the noise has a certain level.
Here I won’t show you anything mathematical, instead I want to show you that not always the things are simple as they seem.

The experiment.

As base for the experiment, I created a simple circuit with my Netduino. Nothing special about it: it’s a circuit seen many times.
The Netduino SPI drives a 74HC595, which dirves a 7-segment display. The display itself has the only meaning to show a certain “pattern” to the observer (me). Of course, it’s much more simple to recognize a number, than a sequence of leds. That’s the way I’ve chosen a display over eight leds.
The Netduino runs a very simple program, which has to present sequentially the 16 digits of the hex-base. Each digit is held for 500ms, and the sequence is kept running forever.

    public class Program
    {
        /// <summary>
        /// Segment pattern for the hex-digits
        /// </summary>
        static readonly int[] Digits = new int[16]
        {
            0xBF,   //0
            0x06,
            0xDB,
            0x4F,

            0xE6,   //4
            0x6D,
            0xFD,
            0x07,

            0xFF,   //8
            0x6F,
            0xF7,
            0x7C,

            0xB9,   //C
            0x5E,
            0xF9,
            0x71,
        };


        public static void Main()
        {
            //define the SPI configuration
            var config = new SPI.Configuration(
                Pins.GPIO_PIN_D10, // SS-pin
                false,             // SS-pin active state
                0,                 // The setup time for the SS port (not used)
                0,                 // The hold time for the SS port (not used)
                true,              // The idle state of the clock
                true,              // The sampling clock edge
                1000,              // The SPI clock rate in KHz
                SPI_Devices.SPI1   // The used SPI bus (refers to a MOSI MISO and SCLK pinset)
            );

            //define a single-cell buffer used by the "Write" method
            int i = 0;
            byte[] buffer = new byte[1];

            //open the SPI port
            using (var spi = new SPI(config))
            {
                while (true)
                {
                    //issue the digit pointed by the index
                    buffer[0] = (byte)(Digits[i] ^ 0xFF);
                    spi.Write(buffer);
                    i = (i + 1) & 0x0F;

                    //small delay
                    Thread.Sleep(500);
                }
            }

        }
    }

Note 1: The segment pattern follows the “standard” map used by the 7-seg displays. Bit #0 maps to segment “A”, whereas bit #7 maps to the decimal point.
Note 2: I used to make the DP on for the even digits, and off for the odds.
Note 3: The display I’ve used is a common-anode (toward +5V), so the activation logic is reversed. That’s explain the XOR-op.

I won’t change anything in the above program, other than the SPI clock rate, which is initially equals to 1 MHz (=1000). I would have used an higher clock rate (e.g. 10 MHz), but my scope has a limited bandwidth (100 MHz), and the waveform would not be shown as it is.
The target of the experiment is showing how the SPI signal is at the 74HC595 pins, upon several different wiring.

Tight wiring.

That’s the reference. Everything is wired very tight, keeping the wires as short as possible. Also the grounding (which is *very* important) is shared on the same bread-board, and the supply is given by the Netduino itself.

The circuit is working fine (tested up to 40 MHz of clock-rate, just for your information).

The waveform is perfectly squared: no noise, nor delays.
The upper trace is the SCLK, while the lower is the MOSI.

Shielded cable.

The second test is performed using a 2.5m (about 8 ft) of multi-pole shielded cable of good quality. The problem is about the SPI, which needs at least three signals (SCLK, MOSI, SS), plus ground. For a bidirectional data exchange we’d need another wire.
The circuit is still on the bread-board, but the Netduino is moved off the area. The supplies are separate: the Netduino is supplied via USB, which the HC595 circuit via a regulated power supply.
The ground is shared by connecting the cable shield to both sides.

Again, there’s a little distortion of the signals, but the data transfer is still reliable. The shielded cable works correctly, but I should have to “adapt” the wires at the HC595-side, by “terminating” each signal with a proper resistor. I didn’t for simplicity of comprehension.

The problem is the cost and the thickness of the cable.

Un-shielded cable.

The third test is performed using a 3m (about 10 ft) of multi-pole cable of poor quality. It’s cable for phones, burglar alarms, and similar wiring. Very cheap and thin (although the mine has only three wires: for the ground I’ve used another wire).
Again, the Netduino supply only itself, and the HC595 is supplied by a separate power.

The waveform is clearly getting worse, but the circuit still counting correctly.

The waveform shows rippled, thus it’s interesting to make an attempt by raising the clock rate.

Un-shielded cable at 2 MHz.

Doubling the clock-rate the result is getting even worse. However, the circuit seems still working fine.

Un-shielded cable at 5 MHz.

At 5 MHz the signals are almost unrecognizable, and -yes- the circuit is not working anymore. It displays strange patterns, sometime correct, but mostly randoms.

Effect of the noise on the un-shielded cable.

Let’s take the clock back to 1 MHz, but let’s try to see what happens when a noise-source is close to the cable.
For instance, we might think to another cable, close to the signals’ one, used for motors, inverters, or many others loads that involves “high-frequencies”.

In this case, I took the same shielded cable of the previous test, but I’ve used the shield as “emitter”. Basically, I’ve connected the shield to a square-wave generator (about 4 MHz), and I’ve let the cables over the un-shielded. There’s *NO* metallic connection, but for capacitive coupling (i.e. electrostatic) there’s an interference on the signals’ cable.

The resulting waveform by the HC595 is clearly showing how the noise “sums” to the useful signals.
Of course the circuit is not working!

Conclusions.

The SPI is not a good way to transfer data on long wiring: too wires, too high clock rate. But I wanted to highlight you the effects of a long wiring on a relatively high speed.
Of sure I’d bet on the classic serial port (i.e. UART), which needs just two signals and ground. However, even the RS-232 interface cannot be used for lengths over 15m (50 ft).
For very long distances, the speed must get lowered, and the things are getting harder. However, there are many interesting ways to solve small projects without getting crazy.

LcdBoost library for Netduino

Introduction.


This article show a concrete application of the circuit presented in my previous post.
Although the hacking is something versatile, it has been focused on driving LCD modules in general.
Here is a presentation of a small yet powerful library to simplify the graphic management, even having few memory resources.

Hardware.

There’s almost no changes from the circuit shown in my past article: just some improvement, which has been tested over two-three different kinds of LCD modules. Every time, with no problems.


For my convenience, I created the circuit on a piece of proto-board. I know, it’s not the best solution I could do, but it seems working okay. It’s easy to connect, and it leaves the Netduino pins free for further extensions.


I just added a transistor more, to drive the LCD backlight, where available. Nothing special, but it came almost for free, because luckily on the same Netduino connector there’s a PWM output also.
By the way, there’s no power supply, and most of the LCDs are using the old, faithful, +5VDC. Thus, I used a dedicated connector, using the same pinout as the *duino like connector. It means almost nothing, but it’s worthwhile keeping almost the same pinout pattern, as for convention.
Moreover, this separate power connector yields to a dedicate power supply, instead of overloading the Netduino’s embedded regulator.

Software.

Having a very fast data transfer offers the possibility to structure the library better. Abstraction is asking often a little more of memory resources, but also yields to a better integration of modules. The result is somewhat amazing, at least for a managed device as Netduino is.

First off, I wanted to separate the two layers involved in the UI: the physical and the logical. The physical layer is meant as the “driver”, which actually knows how is the LCD module, its features, and much more. The logical layer should not know anything about the hardware, instead has to organize the user’s API at best, so the user will find comfortable interacting with any display.
Of course this is just the goal: we must bear in mind that never ever will achieve a WPF-like APIs.

Secondly, I wished to offer the APIs in two flavors. Okay, the library is actually the same, but the user can choose to access the display in a imperative-way, or in a declarative-way. However, you can mix all that: no exclusivity at all.

The imperative way is the most intuitive (really?), which came from our childhood. Most of the personal computer had no enough resources, and the “do this”/”do that” programming manner became the most famous. Both the code samples contained in my old post about LCD driving with SPI, are shaped in the imperative fashion.
The declarative way is much more powerful, elegant, and -I’d add- intuitive. Instead of polluting our code with specific actions, let’s declare a bunch of “object”, which we’ll interact with. Each object has its own properties, along with methods. Isn’t sounding familiar?
Further I’ll show a small example of using the LcdBoost library, taking advantage of its declarative APIs.

How is this library made?

As stated, the library is designed to be a “satellite” project to be linked to your own application. You shouldn’t copy-and-paste modules, which leads to errors, and misalignment.
The user interact normally with the logical layer, although it can access the specific physical layer wherever some custom chip-tailored function should be performed. For instance, often the LCD modules are based on the Hitachi HD44780 chip, which offers a character pattern customization. This feature is specific for that chip, thus should be accessed directly to the driver instance.
Also, the library is meant to be improved, and extended. Both the logical and the physical layers are structured to be easily extended. Physical drivers are pluggable, and the logical graphic entities are also pluggables.
At the moment of writing this post, there’s only support for character matrix LCD modules. I’d like to drive some dot-matrix module, but I’m not sure to be able to do it.

The imperative access consists in just three methods:

        /// <summary>
        /// Clear the entire screen
        /// </summary>
        public void Clear()
        {
            // ...
        }


        /// <summary>
        /// Set the starting (reference) position
        /// to be used by any further text operation
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void SetCursorPosition(
            int x,
            int y
            )
        {
            // ...
        }


        /// <summary>
        /// Write a text string (as plain ASCII) on the video cache
        /// </summary>
        /// <param name="text">The string to be written</param>
        /// <remarks>
        /// The text starting reference has to be set by using the <see cref="SetCursorPosition"/>.
        /// After this call, the logical position is moved accordingly
        /// </remarks>
        public void Write(string text)
        {
            // ...
        }

It’s really the minimum, and -honestly- I would not care so much, in favor of the declarative APIs (which I’m proud of!)

Okay, I’m a big fan of WPF, thus I *tried* to mimic that approach. The problem is that WPF would require *TONS* of memory, plus several parts of the regular framework, not implemented in the .Net Micro Framework.
So, the declarative API allow to operate with objects, which must implement a common interface:

namespace Toolbox.NETMF.Hardware
{
    /// <summary>
    /// Fundamental interface for implementing any graphic element
    /// to be managed in the declarative-way by the LcdBoos library
    /// </summary>
    public interface ILcdBoostElement
    {
        /// <summary>
        /// Indicates whether the graphic element is hidden or not
        /// </summary>
        bool IsHidden { get; }

        /// <summary>
        /// Renders the element's cache onto the video viewport
        /// </summary>
        /// <param name="cache">The target video cache to be filled</param>
        /// <param name="container">The parent container bounding rectangle</param>
        void Render(
            LcdBoostVideoCache cache,
            LcdBoostRect container
            );
    }
}

The library comes with just two “renderable” objects (so far):

It’s clearly limited to the character-matrix modules, but surely enough at first attempt.
Again, the LcdBoostElementCharPoint is a particular case of the more generic LcdBoostElementTextArea. It has been tailored for a single character entity, but is performing much better due the fewer calculations.

Performance.

Well, I had hard time to believe my eyes: the rendering is blazing fast. The physical driver has been improved several times, always within a compromise of performance and readability.
I must admit that the only result I have are for character matrix display, all based on the Hitachi HD44780 chip. The “practical” result is that the slowest part is surely the LCD itself, but…I mean the *real* LCD: the crystals! It looks that the crystal inertia is so huge, that you can reach 2-3 fps. At this point, the Netduino speed is a minor problem.

Anyway, here is a couple of snapshots taken with the scope.
The first one shows the overall rendering process (logic arrangement, plus physical transfer), along the timer cycle (100ms). The high-level interval is the actual busy period.


The second picture (below) is showing the physical transfer time via SPI. Since my display is a 20×4 character matrix, the transfer is accomplished on two sequential steps. The overall transfer takes less than 20 ms.

NOTE: the timing of the pictures is based on the demo game presented below.

A simple demo game.

To be attractive, a sample should be something funny.
Here is a simple pong-like game. The game itself has no meaning: using a 20×4 display is still playable with difficulty.
The interesting thing is how readable is the code, and how simple is creating even complex tasks. I’d also add that a similar approach will probably improve both efficiency, and compactness of the resulting code.
Do you have ever programmed any XNA game?
Well, the concept is quite simple: declare your resources (e.g. bitmaps, sounds, etc), then add the game logic. All the life is hanging to a “loop” which renders the game scenery. Here is the same.
Just add your ILcdBoostElement-derived elements to an array, that will be you resource-bag to be rendered. Afterward, the actual rendering will be performed automatically within a timed loop.

namespace Toolbox.NETMF.Hardware
{
    /// <summary>
    /// A demo of a simple pong-like game
    /// </summary>
    /// <remarks>
    /// The aim of the demo is demonstrating how simpler is
    /// creating even pretty complex games, by taking advantage
    /// of the declarative approach, instead of the imperative one.
    /// 
    /// The paddle is controlled by any numeric port
    /// 
    /// NOTE: although this demo can work on any lcd size,
    /// has been tailored for a 20x4 char matrix LCD module
    /// </remarks>
    class DemoPong
    {
        private const int BrickRows = 2;
        private const int BrickColumns = 16;
        private const int TotalBricks = BrickRows * BrickColumns;

        private const int AvailablePaddles = 5;

        private static LcdBoostElementCharPoint[][] _elem_bricks;
        private static LcdBoostElementTextArea _elem_paddle;
        private static LcdBoostElementTextArea _elem_score;
        private static LcdBoostElementTextArea _elem_paddles_left;
        private static LcdBoostElementCharPoint _elem_ball;
        private static LcdBoostElementTextArea _elem_gameover;

        private static Random _rnd;


        public static void Run(
            LcdBoostProxy lcd,
            NumericInput paddle)
        {
            //init the random number generator using a pseudo random seed
            _rnd = new Random(DateTime.Now.Millisecond);

            //define an array for containing all the UI-elements
            var elements = new ILcdBoostElement[TotalBricks + 6];
            var elem_count = 0;

            /**
             * Allocates the resources to be used in the program
             * this is very similar to the "sprite" approach
             **/

            //right-side wall
            var wall = new LcdBoostElementTextArea();
            wall.Text = "||||";
            wall.Bounds.Left = 16;
            wall.Bounds.Top = 0;
            wall.Bounds.Width = 1;
            wall.Bounds.Height = 4;
            elements[elem_count++] = wall;


            // ...


            /**
             * Create a new session of game.
             * The session contains only the dynamic data used
             * by the game. The logic is meant to be outside.
             * That's much like a functional approach
             **/
            var session = new GameSession();
            session.NewBall();


            /**
             * Master clock for the game refresh
             * 
             * Notice that the clock is handling the display refresh
             * at 10 fps, but the game logic has to be slowed down
             * because would be too fast to play
             **/
            int clock_counter = 0;
            var clock = new Timer(
                _ =>
                {
                    //invoke the game logic
                    Worker(
                        session,
                        clock_counter++
                        );

                    //refresh display
                    lcd.Dump(elements);
                },
                null,
                100,
                100);


            Thread.Sleep(Timeout.Infinite);
        }


        /// <summary>
        /// The game logic
        /// </summary>
        /// <param name="session"></param>
        /// <param name="clock_counter"></param>
        private static void Worker(
            GameSession session,
            int clock_counter)
        {
            //stop logic when there'are no more paddles left
            if (session.PaddlesLeft <= 0)
                return;

            //timer scaling to slow down the game logic
            if ((clock_counter & 0x07) != 0)
                return;

            //retrieve the current ball coords
            int x = _elem_ball.X;
            int y = _elem_ball.Y;

            // ...

        }


        /// <summary>
        /// 
        /// </summary>
        private class GameSession
        {
            /// <summary>
            /// Overall score
            /// </summary>
            public int Score;

            /// <summary>
            /// Paddles left
            /// </summary>
            public int PaddlesLeft = AvailablePaddles;

            /// <summary>
            /// 2D vector defining the ball speed
            /// </summary>
            public readonly Vector BallSpeed = new Vector();


            /// <summary>
            /// Init for a new incoming ball
            /// </summary>
            public void NewBall()
            {
                int n = _rnd.Next(10000);

                //gets the new ball position
                _elem_ball.X = 2 + n % 12;
                _elem_ball.Y = 0;

                //gets the new ball speed
                this.BallSpeed.DX = n < 5000 ? -1 : 1;
                this.BallSpeed.DY = 1;

                //update the paddles left box
                _elem_paddles_left.Text = "_" + this.PaddlesLeft.ToString() + "_";
            }
        }


        /// <summary>
        /// Simple class for defining a 2D vector
        /// </summary>
        private class Vector
        {
            public int DX;
            public int DY;

            public void InvertX()
            {
                this.DX = -this.DX;
            }

            public void InvertY()
            {
                this.DY = -this.DY;
            }
        }

    }
}

As seen previously, in the performance section, the rendering loop is timed to refresh the display on every 100 ms, that is 10 fps. It’s fairly poor as it were a normal video game, but it’s indeed too fast to be playable. Thus, the logic update has been scaled down of a factor of 8.

The paddle controller deserves a word of mention.

The poor-man game controller

In any decent arcade game, the controller is an important component. However, I’m not going to produce video-consoles, nor focusing on the comparison on game controllers. I just needed a quick-and-dirty way to move the paddle for my pong-like game, but…I also realized that I hadn’t anything fitting the goal.
So, I took my bag of trashy stuffs, carefully collected by my (poor) dad, and I began digging. The most obvious thing is the last to be considered: why not a normal brushed motor? My dad had dozen of small motors, so I got one of them, probably originally built on a old tape-deck.
The circuit is somewhat ridiculous: just a 1/2 voltage divider, and the motor. Okay, I’ve seen that a capacitor is a good way to get the reading more stable.


The voltage divider just creates an halfway voltage, so that the working point for the ADC is about in the middle of the range. As stated, the capacitor yields more stability to this voltage point. Finally, the motor is connected from this voltage divider, and any Netduino analog input.
When you take the motor spinning by using fingers, it works actually as a dynamo, and produces a little voltage. This voltage can be either positive or negative respect to the voltage divider point. The software samples the analog input periodically, and converts the samples accordingly.

As long you don’t get the motor spinning fast, there’s no danger at all.

Conclusions.

Once again, Netduino does it better.
It’s just another little piece of knowledge to get you working better with Netduino, and the .Net Micro Framework. Sometime the solution isn’t coming quickly as expected, but collecting experience helps a lot.

Future goals is hacking the new gaming console Netduino-based: the PIX-6T4, by Nwazet.

The library is part of the Cet Open Toolbox, and can be downloaded together with schematics and Fritzing diagrams.

Infrared transmitter driver for Netduino

Introduction.


There are several contexts where the infrared (IR) remote commanders are really useful: our home is plenty of appliances which are IR based. TVs, Air-conditioning, HiFi-set, games, and lot more. This technology is still alive, because is very simple to implement, and requires very little resources to be realized.
Many users are asking about how to send infrared (IR) messages using a Netduino. That’s because the pleasure of programming such a little board as Netduino is, inspires easily to create solutions where the IR communication may be involved.
At first glance seems hard making a real-time operation for a managed-code platform, and several users have solved this problem connecting an Arduino-like board to the Netduino. That is a very good solution, even pretty elegant, when well-designed. However, it sounded me like a challenge: is it possible for the Netduino sending IR messages without any external “help”?
Well, I’ve got it!

How is an IR message?

Well, there is a very good, yet detailed page, where the principle of sending data through infrared ray is explained. I guess it’s completely useless to rewrite what’s described there.
http://www.sbprojects.com/knowledge/ir/index.php
You can see that there are several protocols, almost every big manufacturer created its own protocol. Here is not important make any comparison between protocols: the aim is to implement them, because we do have some appliance using a certain protocol. So, we need that implementation.
Again, the real challenge is adding the minimum hardware to the Netduino, and make it able to reproduce almost any IR protocol.

How it works?

Once again, I chosen the SPI as primary device for generating the waveform. That because is very simple: just a shift register, and nothing else. And very fast, indeed.
If you take a look at some previous post of mine, it’s clear to see on the scope what’s the behavior of the signals outgoing from the Netduino SPI. If you perform the transfer of a single, long byte array, the SPI is able to shift the data out without almost no delay between bytes. It’s like a streaming.
This privilege gave me the idea on to shape the required waveform: create the bit-pattern on a long buffer, then let the SPI shift it all at once.
The only missing piece is obviously a good driver for the IR-led, since it requires enough current to “light” a room. Okay, we can’t see the IR light, but for the IR receiver “eye” the room is pretty dark, and even a little led can be an huge difference. Try yourself to light up a small led, when the room is completely dark.

Here follows a chart with the detailed principle of working.

Note that the reference is to the Philips RC-5 protocol, but it might be anyone else.

The physical driver circuit.

The circuit is really trivial, and it could be the same circuit pattern used many times for a normal led. By the way, an IR led actually *is* a led, but we need a lot more current flowing through.
The circuit could have been even easier, if only we avoid the ability to share the SPI with some other device. Personally, I would not like losing the ability to drive a SPI-RTC, for instance, because the IR driver. We should drive both.
Thus, there is a simple logic: an AND-gate, where one of the input is the “IR-driver enable”. When the enable is low (zero), no activity on the SPI can involve the IR stage.

The circuit is using two NAND gates (74LS00), because I haven’t at home the right chip. I would recommend the 74HC08 instead, which is a 4x AND gates, HCMOS.

Some consideration about the led current.

If you take a look at the resistor for the led is very low when compared to the typical values you are used to choose. I’ve used 22 Ohms, which is about 10 times lower than a normal led, but I should have used even a 2.2 Ohms (typical for most remote commands).

A straightful computation yields a current of about 150mA for a 22 Ohms resistor, and over 1A for a 2.2 Ohms. Such a high current is surely enough to burn the led, and it’s too high even for the Netduino supply.
You might wonder why a so high current doesn’t actually damage any part.
The answer is very simple: these values are “peaks” for a bunch of microseconds, “spikes” so short, that the average heating power is much less than the power led on the Netduino board.

If you are scared to burn your IR led, I’d suggest a small extra to the circuit. No manufacturer will ever add such a circuit, because is too expensive. However, the hobbist perspective is quite different, and I prefer to give you an opportunity to keep your parts safer.

The trick is simple: the big capacitor (1000 uF) acts as charge accumulator. The stored energy is surely enough to drive the led for some millisecond, but if you try to drive the transistor continuously (e.g. a breakpoint or a bug), the capacitor will lose all its charge, and the actual current will be limited by the additional resistor.

The Infrared library.

The library is targeted for any protocol within the range of the domestica appliances. I don’t know the IRDA protocol, nor I think should be feasible (nor convenient).
At the moment I’m writing this post, the library embeds only the Philips RC-5 (Extended mode included), for transmission. However, it’s very easy to implement many other protocols, since they are very similars.
Please, check the library progression, because I’ll add the missing modules.

Testing the circuit.

My primary goal is sending commands from Netduino to my Maerklin railroad model.

In my case the biggest effort is finding out the protocol, because Maerklin does not give any specs about its devices. However, by using my scope and a small IR-receiver module, I was able to understand that Maerkiln uses the Philips RC-5 Extended protocol.

Using the library is really simple. In the following snippet there’s an example where I wanted to mimic the original remote commander of my Maerklin railroad model.
I have used just three buttons: speed-up, speed-down and change direction. For each button, its event handler embeds a different command to be sent via infrared, according to the Maerklin code set below.

namespace Toolbox.NETMF.Hardware
{
    public class Program
    {
        /**
         * Maerklin remote commander codes:
         * light:   1.T.11000.1010000
         * btn 1:   1.T.11000.1010001
         * btn 2:   1.T.11000.1010010
         * btn 3:   1.T.11000.1010011
         * btn 4:   1.T.11000.1010100
         * btn -:   1.T.11000.0010001
         * btn +:   1.T.11000.0010000
         * dir:     1.T.11000.0001101
         **/
        private const int Address = 0x18;

        private const int SelectLight = 0x50;
        private const int SelectTrain1 = 0x51;
        private const int SelectTrain2 = 0x52;
        private const int SelectTrain3 = 0x53;
        private const int SelectTrain4 = 0x54;

        private const int SpeedDown = 0x11;
        private const int SpeedUp = 0x10;

        private const int Direction = 0x0D;


        public static void Main()
        {
            //create the infrared transmitter driver
            var irtx = new InfraredTransmitter(Pins.GPIO_PIN_D8);

            //create the codec to be used
            var codec = new InfraredCodecRC5(irtx);
            codec.ExtendedMode = true;

            //define the button for decrement speed
            var btn_dec = new InterruptPort(
                Pins.GPIO_PIN_D0,
                true,
                Port.ResistorMode.PullUp,
                Port.InterruptMode.InterruptEdgeLow
                );

            btn_dec.OnInterrupt += (a_, b_, dt_) =>
            {
                codec.Send(Address, SpeedDown);
            };

            //define the button for increment speed
            var btn_inc = new InterruptPort(
                Pins.GPIO_PIN_D1,
                true,
                Port.ResistorMode.PullUp,
                Port.InterruptMode.InterruptEdgeLow
                );

            btn_inc.OnInterrupt += (a_, b_, dt_) =>
            {
                codec.Send(Address, SpeedUp);
            };

            //define the button for the direction
            var btn_dir = new InterruptPort(
                Pins.GPIO_PIN_D2,
                true,
                Port.ResistorMode.PullUp,
                Port.InterruptMode.InterruptEdgeLow
                );

            btn_dir.OnInterrupt += (a_, b_, dt_) =>
            {
                codec.Send(Address, Direction);
            };

            Thread.Sleep(Timeout.Infinite);
        }

    }
}

Here is a small demo of the project:

Finally, it seems that this IR solution is able to solve the problem of another geek. The deal of Laurent Ellerbach was to send IR commands from the Netduino to his amazing Lego village.
Well, I’m really proud to have helped him.

Conclusion.

If your goal is having a simple yet versatile IR transmitter to add to your Netduino, then maybe this circuit is for you. However, the main reason of this project is demonstrating that even a simple real-time operation can be solved by taking advantage of certain features of your Netduino.
If you find this library useful, and you implement it somewhere, feel free to add a link to pictures, videos, or whatever else.

The library is now part of the Cet Open Toolbox, and can be downloaded together with schematics and Fritzing diagrams.

Netduino SPI: “S” is for “Speed”

Introduction.

One of the most used peripheral of the Netduino microcontroller is the SPI. Its simplicity together with its speed makes it a very good medium to exchange data from the microcontroller (thus your program) and other external devices. The marker is plenty of shields and circuits basing their data exchange on SPI, plus a vast series of ICs are SPI-ready, making a logic connection a pretty easy task.
There are several articles, tutorial and programs demonstrating how to use the SPI: most of them are related to some specific shield. That’s not what we are talking about; instead it is interesting to point out how to interface our own logic, and obtaining a good performance.

Using the SPI.

Many times we need to expand the number of I/Os of our board. Sometimes we need a solution to realize a parallel transfer, since the base framework does not offer that feature.

A simple solution to achieve that is using a normal shift-register chip. As the name suggests, a shift-register takes just one bit at once as input, and shifts it along a byte-register (8 cells). The shift is not automatic, but it must be accomplished by the “clock”: each clock event means a bit-shift. There is not any constraint on the number of clocks applied: simply the data overflow, and we must take care about the exact number of clocks.
This brief description depicts a “serial-in-parallel-out” logic, but there are the “parallel-in-serial-out” and other flavors as well.
All is well described as “synchronous-communication”. Vice versa, an “asynchronous-communication” (e.g. the UART) relies on the implicit matching of the data-rate: if they don’t match the device involved don’t understand each other.
When we have to connect chips together (i.e. very short distances) the synchronous choice is surely better: offers high throughput, reliability, frequency independence and lot more. Its price is a small logic and a certain number of lines to manage it.
When is a synchronous choice disallowed? When we need to exchange data over relatively long distances and when we cannot afford the payload of many wires to connect the devices.

Visual devices connected via SPI.

When we begin playing with Netduino, the first experiences are driving leds, lcds and other “visual” stuffs. That’s absolutely normal, because the visual-way is the most intuitive and direct solution for having a concrete feedback on what our program is doing.
Why should the SPI be involved with visual devices?
Well, just after our “hello-world” program being able only to blink a led, we would try connecting two-three or more leds. Our Netduino luckily provides many I/O ports, so it is very easy to add even a dozen of leds. What’s the sense of wasting all your precious ports just for driving leds?
The Mighty Stefan is one among the first running this “gold rush” around the shift-registers. He enjoyed so much the connection of a shift-register that drove 8 leds, who wanted going further, chaining several chips as a cascade of bits.

At the moment I am writing, I know he connected up to 5 shifters linked together.

However, my very first attempt to use a shift-register with my Netduino was for driving a LCD module. I found reading text much exciting than seeing a psychedelic game of leds. Szymon presented a very good tutorial how to interface a common 16×2 LCD module using a 75HC595 shift-register. It worked at first run.
I would point out that here we will talk about the 74HC595 chip, but there is *not* anything of specific on it. This model is often used, due to its versatility, and it would be preferable to keep the discussion on well-known devices, so everyone can test it easily.

Where is this article going to?

Well, the “problem” could not be an actual problem; it depends on what we are looking for. However there are situations where a simple connection of a shift-register doesn’t solve our problems, otherwise it may happen that the data speed is far from the “megabits-promise” of the manufacturer. The microcontroller specifications say that the SPI could reach even the processor clock, but that sounds much more a theoretical value than an effective data-rate.
We will analyze two hardware solutions to connect a shift-register: one is trivial, the other one is more sophisticated, but it offers a much higher performance.
A generic task will be considered in the two contexts; the program should transfer a series of bytes to an external device, but each byte available should be “notified” to the target consumer. For example we may suppose to feed a parallel DAC, where each 8-bit sample must be latched onto the converter, so that the analog output will be set accordingly. Please, consider this example as merely illustrative. Several DACs have the SPI interface built-in.
The SPI clock frequency is the same for both the circuits and it has be chosen as 2 MHz.

The easy way.

Let’s first analyze how it works the simplest and most common connection of a 74HC595 shift-register.
Here is the sample code for the test. Our goal is to transfer a series of bytes to the register as fast as possible. The buffer transfer is repeated indefinitely, only waiting for a short pause between the cycles. Along a buffer transfer we should expect a byte-rate of approximately 2M / 8 bit = 250 KBytes/s.
Will we able to reach that?

    public class Program
    {
        private static SPI SPIBus;

        public static void Main()
        {
            // Defines the first SPI slave device with pin 10 as SS
            SPI.Configuration Device1 = new SPI.Configuration(
                Pins.GPIO_PIN_D10, // SS-pin
                false,             // SS-pin active state
                0,                 // The setup time for the SS port
                0,                 // The hold time for the SS port
                true,              // The idle state of the clock
                true,              // The sampling clock edge (this must be "true" for the 74HC595)
                2000,              // The SPI clock rate in KHz
                SPI_Devices.SPI1   // The used SPI bus (refers to a MOSI MISO and SCLK pinset)
            );

            // Initializes the SPI bus, with the first slave selected
            SPIBus = new SPI(Device1);

            DoWorkSlow();
            //DoWorkFast();
        }

        ///
        /// Send 8 bytes out to the SPI (one byte at once)
        ///
        private static void DoWorkSlow()
        {
            //set-up a one-byte buffer
            byte[] buffer = new byte[1];

            while (true)
            {
                for (int i = 0; i < 8; i++)
                {
                    buffer[0] = (byte)i;
                    SPIBus.Write(buffer);
                }

                Thread.Sleep(5);
            }
        }

    }

Note: part of the code was “stolen” from the Stefan’s tutorial on SPI, from the Netduino wiki section.

The code shows clearly an overhead of computation, because there’s no way to send a single byte directly the SPI driver. Instead, we must create a single-byte buffer and then populate the unique cell with the desired value.
Another fault of this approach is that we *must* take care of the sending of every single byte, while it could be much more useful making other operations.
Here is the logical timing sequence. Note that on this chart the time proportion is not respected.

Every byte (i.e. every Write call), the SSEL line (Slave Select) will fall and keeps low as long the stream is over. Since the “stream” is just one byte, the SSEL will rise after the 8th bit.
The clock (SCLK) pulses for 8 periods. The data (MOSI) is shifted out the Netduino on each clock falling edge. That is because the 74HC595 needs to sample the data (MOSI) when its clock input rises. To avoid any misinterpretation of data, the best thing is keeping the data perfectly stable during the SCLK rising edge.
The rising edge of the SSEL line is also used to latch the byte shifted on the 74HC595 parallel output.
All that does what we expect, but…what is the real timing?

It is easy to see the 8 single-byte transfer, separated by the pause. It seems that the real delay is almost 6ms instead of 5, but maybe this is not a problem.
Much more interesting is measuring the time that elapses from the beginning of a byte and the next one. For example, this time could be taken as the period between two consecutive rising edges of the SSEL line.
The scope shows 368us, that is about 2.7 KBytes/s: around 100 times slower than the expected rate!

Finally, here is both the schematic and the breadboard layout, for the ones want to build and test this circuit.

The smart way.

The program is almost the same as before, even much simpler and efficient, because the buffer will be sent “as-is”. Our application doesn’t care about how the bytes are shifted out: feels like a heaven!
Here is only the difference from the code above.

        ///
        /// Send 8 bytes out to the SPI (buffer at once)
        ///
        private static void DoWorkFast()
        {
            //set-up the desired buffer
            byte[] buffer = new byte[]
            {
                0,1,2,3,4,5,6,7
            };

            while (true)
            {
                SPIBus.Write(buffer);
                Thread.Sleep(5);
            }
        }

Please, bear in mind that the SPI clock frequency is still the same as before, so the expectation is always a throughput of 250 KBytes/s.


The logical timing sequence of the SPI is similar to the one-byte transfer, but now there is a problem: the SSEL line rises at the end of the last byte. How could be latched the preceding bytes onto the 74HC595 register?
We must add some logic to help the circuit. Here is the revised logical timing sequence.

The extra logic must be able to provide a latch clock to the 74HC595 exactly after every 8th bit. To achieve this, we must consider a counter, such as a normal 3-stages counter, because we need to count just up to 8. This counter should also “trigger” some other logic so that we obtain a pulse. Its rising edge can finally latch the data on the register.

The counter is a 74HC4040. It is a 12 stages binary-counter, increments its value every falling edge of the clock, and could be reset pulling high the related pin. In fact, the reset input is connected to the SSEL line, so that when the transfer begins we are guaranteed that the counter is zero.
The SCLK from the Netduino must feed the counter, but we need to invert it. Remember? The 74HC595 shifts on the rising edge of the clock, so the counter must increment itself at the same time. To invert the SCLK line I used a 40106: it is an old Cmos, not as fast as an HCmos, but it embeds 6 inverters with Schmitt-trigger, and it allows a very large power supply range.
Here is the detail of the SCLK (light blue) and the output of the first stage of the 74HC4040 (yellow). Note the propagation delay from the rising edge of the SCLK and the output change is almost comparable with the half of the clock period. Not a good thing and we should have chosen some chip performing better than the 40106.

The 3-stages counter starts with 000, then 001, then 010, up to 111, then rolls back to zero. We will take advantage from the third bit, because it falls from 1 to 0 just after 8 clocks. At this point, the only problem is to create a pulse triggered from the falling edge of the counter output.
The pulse generator is realized by a small analog circuit (R, C and diode), along with a couple of 40106 inverters.

  • Consider the Q2 output of the 74HC4040 at logic level “1” (+5V), just before is dropping to zero. Across the capacitor the voltage is zero, because there is either +5V from the counter side, and +5V on the TRIG point, pulled up by the resistor.
  • As soon the Q2 falls to zero, the capacitor keeps its voltage drop, bringing the TRIG point toward zero Volts as well.
  • However, through the resistor will flow current that charges the capacitor, so the voltage on the TRIG point begins to rise with an exponential shape.
  • Now, the Q2 output switches to the high level. Again, the capacitor tries to keep its voltage drop pushing the TRIG point over the +5V, but the diode limits it.


The Schmitt-trigger inverters need because the signal on input is analog and it is useful to manage it as best, to prevent unpredictably behavior during the transitions. Two inverters in cascade mean just no logic inversion. We only need the Schmitt-trigger capabilities.
Here follows the detail of the pulse succeeding the 8-clocks sequence. Again, note the not-so-sharp fall and rise of the pulse due to the poor performance of the 40106.

The “smart” (and complex) solution has been built. What about the data transfer performance?
Here is the picture showing the buffer transfer separated by the Sleep pause. Again the spacing is much more toward 6ms instead of 5, but that’s not what we are looking for.

Here is the interesting chart: the scope shows clearly a huge increment of speed between a byte and the next one. The actual byte period is about 5.5 us, which is over 180 KBytes/s. This is still far from the theoretical value of 250K, but it seems the best performance the Netduino can do (keeping stable the clock frequency at 2MHz).

Conclusions.

Using this pretty simple extra logic we are able to hugely increment the actual performance of the Netduino SPI. The analog trick is not a reliable way to manage the digital circuits, but sometimes is acceptable.
This article was a half-a-way step to explain a technique to improve the SPI throughput, because it needs for my next project.
Stay tuned!