TERRYのブログ

なにやら書くかもしれません

Netduinoで4桁7セグメントLEDを光らせてみた

f:id:terry_u16:20150927011229j:plain
ちょっと前にNetduino 3 wi-fiが届いたので、
電子工作素人が4桁7セグメントLEDを使って遊んでみました。

Netduinoとは?

Netduinoとは、.NET Micro Frameworkに対応した、
Arduino互換のマイコンボードです。
マイコンのくせにプログラムがC#Visual Studioを使って書けちゃうので、
コーディングもデバッグもかなり楽にできます(主観)。
詳しくは以下の記事でどうぞ。

www.buildinsider.net

今回使うもの

回路

4桁7セグメントLEDについてはこちらで解説がなされているので、
詳しい解説はそちらに丸投げします。
ざっくり言うと1桁あたり8つのLED(7セグメント+小数点)が使われていて、
それを1桁ずつ順番に超高速で点灯させることで4桁分の表示を行っています。
(ダイナミック点灯方式)

1つだけ注意点として、NetduinoのI/Oピンは25mAまでしか耐えられないそうなので、
何も考えず8つ全てのLEDを全力で点灯させると、
8つのLEDの電流が全部カソード側のピンに流れ込んで死ぬ可能性があります。

よってLED1個あたりの電流を25mA÷8≒3mAちょっとに抑えなければなりません。
そこで試しにこんな感じの回路を作って、LED1個あたりに流れる電流を計測してみます。

Netduinoの3.3V端子から適当な抵抗とLED1個を通ってGNDへ流れるだけの回路です。
この7セグメントLEDはアノードが8本、カソードが4本あるのですが、
そのうちの適当な1つずつにNetduinoの+側と-側を繋げています。
この状態で抵抗の両端の電圧を計測してみると0.6Vかかっていたので、
0.6V÷3mA=200Ω以上の抵抗を使えばだいたい安全、ということになります。
というわけで今回は手元にあった220Ωの抵抗を使いました。

そんなこんなで出来上がった回路はこんな感じになります。


コード

こんな感じのコードになりました。
いつも通りC#で良いのでだいぶ書きやすく感じます。
(LEDの点灯パターン定義がめんどくさいですが……)

using System.Threading;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace SevenSegmentQuadLED
{
    public class Program
    {
        /// <summary>
        /// 0~9までのLEDの点灯パターン
        /// </summary>
        static bool[][] numberPattern = new bool[][]
        {
            new bool[] { true, true, false, true, false, true, true, true },
            new bool[] { false, false, false, true, false, true, false, false },
            new bool[] { true, true, false, false, true, true, false, true },
            new bool[] { false, true, false, true, true, true, false, true },
            new bool[] { false, false, false, true, true, true, true, false },
            new bool[] { false, true, false, true, true, false, true, true },
            new bool[] { true, true, false, true, true, false, true, true },
            new bool[] { false, false, false, true, false, true, true, true },
            new bool[] { true, true, false, true, true, true, true, true },
            new bool[] { false, true, false, true, true, true, true, true }
        };

        /// <summary>
        /// Netduinoボード上のアノード側のポートの定義
        /// </summary>
        static OutputPort[] anodePorts = new OutputPort[]
        {
            new OutputPort(Pins.GPIO_PIN_D13, false),
            new OutputPort(Pins.GPIO_PIN_D12, false),
            new OutputPort(Pins.GPIO_PIN_D11, false),
            new OutputPort(Pins.GPIO_PIN_D10, false),
            new OutputPort(Pins.GPIO_PIN_D9, false),
            new OutputPort(Pins.GPIO_PIN_D7, false),
            new OutputPort(Pins.GPIO_PIN_D6, false),
            new OutputPort(Pins.GPIO_PIN_D5, false)
        };

        /// <summary>
        /// Netduinoボード上のカソード側のポートの定義
        /// </summary>
        static OutputPort[] cathodePorts = new OutputPort[]
        {
            new OutputPort(Pins.GPIO_PIN_D0, true),
            new OutputPort(Pins.GPIO_PIN_D1, true),
            new OutputPort(Pins.GPIO_PIN_D2, true),
            new OutputPort(Pins.GPIO_PIN_D3, true)
        };


        public static void Main()
        {
            int count = 0;

            while (true)
            {
                // 1の位を表示→3ms待機→10の位を表示→3ms待機→……を高速に繰り返す
                clearDisplay();
                writeNumber(count % 10, 0);
                Thread.Sleep(3);
                clearDisplay();
                writeNumber((count / 10) % 10, 1);
                Thread.Sleep(3);
                clearDisplay();
                writeNumber((count / 100) % 10, 2);
                Thread.Sleep(3);
                clearDisplay();
                writeNumber((count / 1000) % 10, 3);
                Thread.Sleep(3);

                // カウントアップ
                count++;
            }
        }

        /// <summary>
        /// 指定した桁に数字を表示します。
        /// </summary>
        /// <param name="number">表示する数字(0~9)</param>
        /// <param name="digit">桁数(0~3、10のn乗部分に相当)</param>
        static void writeNumber(int number, int digit)
        {
            // 指定されたカソードをLOWにして電流が流れ込んでくるようにする
            cathodePorts[digit].Write(false);
            writeNumber(number);
        }

        /// <summary>
        /// 数字を表示します。
        /// </summary>
        /// <param name="number">表示する数字(0~9)</param>
        static void writeNumber(int number)
        {
            for (int i = 0; i < 8; i++)
            {
                anodePorts[i].Write(numberPattern[number][i]);
            }
        }

        /// <summary>
        /// 表示を全てリセットします。
        /// </summary>
        static void clearDisplay()
        {
            foreach (var anodePort in anodePorts)
            {
                anodePort.Write(false);
            }

            foreach (var cathodePort in cathodePorts)
            {
                // カソード側のピンをHIGHにして電流が流れ込まないようにする
                cathodePort.Write(true);
            }
        }
    }
}

動かしてみる

www.youtube.com

ちゃんと動きました。やったね!
表示する部分ができると無性に温度計とか距離センサとかと連携させたくなってきますね。