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とかが関係してそうです。

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

8月27日(金)のつぶやき

2010-08-28 01:29:04 | Twitter
07:50 from web
6 + 6 - 4 / 2
Sim0000への問題。2 4 6 6を組み合わせて10を作れ。 http://shindanmaker.com/27613
07:52 from web
(√(8 / 2 + 6 + 0)) ^ 6 Sim0000への問題。 6 2 6 8 0を組み合わせて1000を作れ。 http://shindanmaker.com/28550
07:53 from web
10と3を作って10^3とするか、√10と6を作って(√10)^6とするあたりが定石みたいだ。
08:25 from Echofon
めもめも RT: @morecat_lab: Arduinoを使ったAVR用デバックツールavrsh。リモートでAVRのレジスタを叩いて動作をいろいろ試せる。シミュレータでは試しきれない動作の確認用に便利かも http://bit.ly/aU0b2a
10:53 from Echofon
バリウム飲んだ~
12:21 from web
バリウムを飲んで思ったこと。つくづく観測は対象に影響を与えるなあ。
13:21 from web
SHA-3 Conferenceおもしろかったみたい。http://bit.ly/c6GKT0 日本勢で唯一生き残っている日立のLuffaにはがんばってもらいたいものだ。
13:35 from web
NETMFのstring (System.String)にはなぜかFormatがない。http://bit.ly/cJaoyJ #netduino
14:18 from Echofon
RT: @hitoriblog: Netduino始めました - ひとりぶろぐ http://bit.ly/cbBDfz
14:33 from Echofon
ToString("フォーマット")で、変換文字にxが使えない。どうやって16進文字列に変換するのだろう? #netduino
15:48 from Echofon
だいじょぶっすか? RT: @yoshichika: はんだづけカフェはエアコンが動かないままです。
15:49 from Echofon
Oh, thanks RT: @skobalczyk: @Sim0000 Here is the code to convert number to hex string on netduino http://bit.ly/dvBIrx
15:53 from Echofon
コモドール64型PC、ホリデーシーズンに発売 http://japanese.engadget.com/2010/08/27/c64/
16:33 from Echofon
英語の140字と日本語の140字って、かなり分量が違う
16:43 from Echofon
const int x = 0; とか。 RT: @OuchOuchOuch: "#define X 0"はダメですか、そうですか。
by Sim0000 on Twitter