Sim's blog

電子工作はじめてみました

NetduinoでキャラクタLCD

2010-08-28 03:26:31 | Netduino
Netduinoでマルチスレッドの続きになります。

Lチカの次というと、やはりキャラクタLCD出力です。小林茂さん(@kotobuki)に頂いたLCD Shieldを使ってみました。元々はArduino用のシールドですが、Netduinoでも使えるか試してみたかったのが動機です。

NetduinoのI/Oピンは入力は5Vトレラントで、出力は3.3Vです。秋月のSD1602HUOB(通販コード P-01797)はVIHのmin(LCDが入力電圧をHとみなす最小の電圧)が2.2Vなので3.3Vでも動作します。



せっかくなのでArduinoのLiquidCrystalクラスとなるべく似せてみました(Arduino 日本語リファレンス)。手抜きなので全機能は含まれていません。
書いたソースです。
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace NetduinoLCD1
{
    public class Program
    {
        public static void Main()
        {
            // write your code here
            Debug.Print("Hello, netduino");

            CLCD lcd = new CLCD(Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D4, Pins.GPIO_PIN_D3, Pins.GPIO_PIN_D2);

            lcd.puts("Hello, Netduino!");

            OutputPort LED = new OutputPort(Pins.GPIO_PIN_D13, false);
            int count = 0;

            while(true)
            {
                lcd.setCursor(0, 1);
                lcd.puts(count++.ToString());
                LED.Write(!LED.Read());

                Thread.Sleep(200);  // wait 200ms
            }
        }
    }

    // Character LCD Arduino like API by Sim
    public class CLCD
    {
        OutputPort rs, e, d4, d5, d6, d7;

        public CLCD(Cpu.Pin rs, Cpu.Pin e, Cpu.Pin d4, Cpu.Pin d5, Cpu.Pin d6, Cpu.Pin d7)
        {
            this.rs = new OutputPort(rs, false);
            this.e  = new OutputPort(e,  false);
            this.d4 = new OutputPort(d4, false);
            this.d5 = new OutputPort(d5, false);
            this.d6 = new OutputPort(d6, false);
            this.d7 = new OutputPort(d7, false);

            begin(16, 2);
        }

        public void begin(uint cols, uint lines){
            Thread.Sleep(50);   // 15ms
            rs.Write(false);
            e.Write(false);
            write4bit(0x03);
            Thread.Sleep(4);    // 4.1ms
            write4bit(0x03);
            Thread.Sleep(4);    // 4.1ms
            write4bit(0x03);
            Thread.Sleep(1);    // 0.15ms
            write4bit(0x02);

            // function set
            //    +----- DL 1:8bit 0: 4bit
            //    |+---- N  1:2line 0:1line
            //    ||+--- F  1:5x11 0:5x8
            // 00101000
            command(0x28);      // 39us

            // display control
            //
            //      +--- D 1:display on 0:display off
            //      |+-- C 1:cursor on 0:cursor off
            //      ||+- B 1:blink on 0:blink off
            // 00001100
            command(0x0c);      // 39us

            clear();

            // entry mode
            //
            //       +-- I/D 1:increment 0:decrement
            //       |+- S   1:shift on 0:shift off
            // 00000110
            command(0x06);      // 39us
        }

        public void clear()
        {
            command(0x01);
            Thread.Sleep(2);     // 1.53ms
        }

        public void home()
        {
            command(0x02);
            Thread.Sleep(2);    // 1.53ms
        }

        public void setCursor(uint x, uint y)
        {
            if(y != 0) y = 0x40;
            x &= 0x3f;
            command(0x80 | y + x);  // 39us
        }

        public void write(uint x)
        {
            rs.Write(true);     // RS = 1
            write4bit(x >> 4);
            write4bit(x);
        }

        public void puts(string s)
        {
            foreach(uint c in s) write(c);
        }

        private void command(uint x)
        {
            rs.Write(false);    // RS = 0
            write4bit(x >> 4);
            write4bit(x);
        }

        private void write4bit(uint x)
        {
            d7.Write((x & 8) != 0);
            d6.Write((x & 4) != 0);
            d5.Write((x & 2) != 0);
            d4.Write((x & 1) != 0);
            e.Write(true);
            Thread.Sleep(1);    // 450ns
            e.Write(false);
            Thread.Sleep(1);    // 37us
        }
    }
}

困ったことは、あまり細かい時間の単位で待てないというのがあります。Thread.Sleep()は1ミリ秒単位の指定しかできません。一応、ミリ秒単位に繰り上げてます。とりあえず動いているのでよしとします。

最初、write4bitやcommandのパラメータはbyteにしてたんですが、(byte)にcastしろというwarningが出ます。command(x + 1);みたいなことをすると、xがbyte型の変数でもx + 1の結果はintになってしまって、command((byte)(x + 1));のように書けというwarningになるというお話です。結局面倒になってbyteはやめてunsignedにしてしまいました。

puts()のところのforeachはかっこいいです。さすがC#って感じです。

classライブラリとかはどうやって作ればいいのか、まだ分かっていません。たぶんnamespaceとかが関係してそうです。

さて、次は何をしようかな。

最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
注文しました (shuji009)
2010-08-28 23:22:03
simさんの上のブログ読むまでは正直、あまり興味無かったのですけど
記事読んで欲しくなったので注文しました。

いつ届くのかなあ?
返信する
re:注文しました (Sim)
2010-08-30 05:58:04
こんにちは、shuji009さん
8/31まで発売記念セールでお安いのでよかったのではないでしょうか。デバッグ機能のついたArduinoみたいな感じで結構いい感じです。入荷は8/31頃らしいので、それからみたいです。
返信する

コメントを投稿