GR KURUMI + LEDマトリクス (その2)
id:currygyu:20130528
前回↑が消化不良だったので、改良してみました。
修正点
・トランジスタアレイを使ってLED用の電源を別に確保
・上記に関連して、電源を3.3Vから5Vに変更
(3.3Vで始めたらトランジスタアレイの電圧降下でLEDが点灯しなくなりました)
・74HC595(x2)でインタフェースをSPI化
はんだ付けを1箇所ずれたまま進めてしまい、半日悩んだりしましたが、どうにか完成しました。
次はフルカラーのLEDマトリクスをいじってみようかと思います。
SPI化したので、GR KURUMIのスケッチもシンプルになりました。
/*GR-KURUMI Sketch Template Version: V1.00*/ #include <RLduino78.h> #include <spi.h> byte leddat[8] = { 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18 }; void disp_update(unsigned long u32ms); // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(9, OUTPUT); // SS(STCP) digitalWrite(9, HIGH); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV128); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); delay(50); attachCyclicHandler(1, disp_update, 1000); } // the loop routine runs over and over again forever: void loop() { byte i=0; for(i=0; i<8; i++){ SPI.transfer((byte)(0x01<<i)); SPI.transfer(leddat[i]); digitalWrite(9, HIGH); digitalWrite(9, LOW); delay(1); } } void disp_update( unsigned long u32ms ) { int y, x; int num = 0; int alive = 0; byte work[8]; for(y=0; y<8; y++){ work[y] = leddat[y]; } for(y=0; y<8; y++){ for(x=0; x<8; x++){ num = 0; /* count around */ if( x != 0 ){ if( ( ( leddat[y] >> ( 8-x ) ) & 0x01 ) != 0 ){ num ++; } } if( x != 7 ){ if( ( ( leddat[y] >> ( 6-x ) ) & 0x01 ) != 0 ){ num ++; } } if( y != 0 ){ if( ( ( leddat[y-1] >> ( 7-x ) ) & 0x01 ) != 0 ){ num ++; } if( x != 0 ){ if( ( ( leddat[y-1] >> ( 8-x ) ) & 0x01 ) != 0 ){ num ++; } } if( x != 7 ){ if( ( ( leddat[y-1] >> ( 6-x ) ) & 0x01 ) != 0 ){ num ++; } } } if( y != 7 ){ if( ( ( leddat[y+1] >> ( 7-x ) ) & 0x01 ) != 0 ){ num ++; } if( x != 0 ){ if( ( ( leddat[y+1] >> ( 8-x ) ) & 0x01 ) != 0 ){ num ++; } } if( x != 7 ){ if( ( ( leddat[y+1] >> ( 6-x ) ) & 0x01 ) != 0 ){ num ++; } } } /* decide */ if( ( ( leddat[y] >> ( 7-x ) ) & 0x01 ) == 0 ){ if( num == 3 ){ work[y] |= ( 0x80 >> x ); } } else{ if( ( num != 2 ) && ( num != 3 ) ){ work[y] &= ~( 0x80 >> x ); } } } } for( y=0; y<8; y++ ){ leddat[y] = work[y]; } }
表示内容は前回と同じライフゲームです。
1秒ごとにタイマで呼ばれるdisp_update関数の中で、表示内容を設定するleddat配列を書き換えています。その辺りをいじれば好きな表示内容に変更も可能かと。
※leddat配列は、ドットを8ビットで表現したものを1行目から順に8行分入れたたものです。
SPIで16ビット送信していますが、最初の8ビットは行指定、次の8ビットは点灯内容となっていて、送信後に74HC595にラッチの信号(KURUMIの9ピン)を入れて表示内容を反映させています。
よくあるやりかたなので、検索すればたくさんでてきます。僕もマネしました。
回路図
https://docs.google.com/file/d/0B9mpDLlbvvN8Wi04eVk1VGpBSkk/edit?usp=sharing
※7/5 配線ミス修正&PDFの窓を出すのやめました
PIC16F916 + 極小3桁LCD
aitendoの極小3桁LCD(3C8-DIP)の続きです。
GR KURUMIでうまくいかなかったのでPICでやってみました。今回使った、PIC16F916はLCDコントローラ機能を持っているので、つないでちょいちょいと設定すればうまくいくはず…だったのですが、LCD用の電圧を外から入れたりするので少し苦労しました。
とりあえず、うまくいったのでソースを貼っておきます。
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, DEBUG = OFF #pragma config FOSC = INTOSCCLK, FCMEN = OFF, MCLRE = OFF #pragma config WDTE = OFF, CP = OFF, PWRTE = OFF #include "pic16f916.h" #include <xc.h> #include <stdio.h> #include <stdlib.h> #define _XTAL_FREQ 8000000 unsigned char digit[10] = { 0x77, /* 0 */ 0x22, /* 1 */ 0x5b, /* 2 */ 0x6b, /* 3 */ 0x2e, /* 4 */ 0x6d, /* 5 */ 0x7d, /* 6 */ 0x23, /* 7 */ 0x7f, /* 8 */ 0x6f /* 9 */ }; void setnum( int num ); /* * */ int main(int argc, char** argv) { int num = 0; OSCCON = 0b01110000; ANSEL = 0x00; LCDSE0 = 0x3f; LCDSE1 = 0x00; LCDPS = 0x88; LCDCON = 0x93; LCDDATA0 = 0x00; /* COM0 */ LCDDATA1 = 0x00; /* COM0 */ LCDDATA3 = 0x00; /* COM1 */ LCDDATA4 = 0x00; /* COM1 */ LCDDATA6 = 0x00; /* COM2 */ LCDDATA7 = 0x00; /* COM2 */ LCDDATA9 = 0x00; /* COM3 */ LCDDATA10 = 0x00; /* COM3 */ setnum( 123 ); while( 1 ); return (EXIT_SUCCESS); } void setnum( int num ) { unsigned char dat[3]; dat[0] = digit[ num / 100 ]; dat[1] = digit[ ( num /10 ) % 10 ]; dat[2] = digit[ num % 10 ]; LCDDATA0 = ( dat[0] & 0x03 ) | ( ( dat[1] & 0x03 ) << 2 ) | ( ( dat[2] & 0x03 ) << 4 ); LCDDATA3 = ( ( dat[0] >> 2 ) & 0x03 ) | ( ( ( dat[1] >> 2 ) & 0x03 ) << 2 ) | ( ( ( dat[2] >> 2 ) & 0x03 ) << 4 ); LCDDATA6 = ( ( dat[0] >> 4 ) & 0x03 ) | ( ( ( dat[1] >> 4 ) & 0x03 ) << 2 ) | ( ( ( dat[2] >> 4 ) & 0x03 ) << 4 ); LCDDATA9 = ( ( dat[0] >> 6 ) & 0x03 ) | ( ( ( dat[1] >> 6 ) & 0x03 ) << 2 ) | ( ( ( dat[2] >> 6 ) & 0x03 ) << 4 ); }
(MPLAB X IDE + XC8)
追記:
回路図を書いてみました。(生まれて初めて)
GR SAKURA + TS174
秋葉原のaitendoでTS174という型番の7セグLCDを買ってみました。データの無い部品なのですが、ネットの知恵をお借りしてGR SAKURAから操作できました。
といいましても、作業の99%は下記サイトの内容そのままです。
こちらの中ほどのリンクから行けるサイトからダウンロードしたHT1621.cppとHT1621.hをWEBコンパイラにアップロードして、引用したサイトのスケッチを入れたところ、ほとんど変更なしで表示までいけました。
いじったのは以下の箇所です。
HT1621.h
#include
をコメントアウト
HT1621.cpp
#include
を#include に変更
gr_sketch.cpp
#include
を#include <../HT1621.h>に変更
※HT1621.hをProject_Rootに入れた場合HT1621 htの引数はdata,wr,rd,csの順で、接続したピン番号を設定
ピン配置ですが、うちのTS174ではバックライトの電源が8ピン、GNDが9ピンでした。引用サイトで使用されているTS119-5とは逆のようです。
最初、一番下の横棒にあたるセグメントが全ての桁で点灯せずあせったのですが、裏面の検品用らしきシールをはがしてアルコールで拭いたところ、点灯するようになりました。
そういうこともあるんだなあと…。
GR KURUMI + LEDマトリクス
GR KURUMIからLEDマトリクスを操作してみました。
暗い行があったり、意図していないLEDが薄くついてしまったり、色々問題ありますね。少しずつ良くして行きたいと思います…。
スケッチは以下です。
/*GR-KURUMI Sketch Template Version: V1.00*/ #include <RLduino78.h> #include <stdio.h> #include <string.h> #define PIN_A_1 2 /* pin9 */ #define PIN_A_2 7 /* pin14 */ #define PIN_A_3 10 /* pin8 */ #define PIN_A_4 5 /* pin12 */ #define PIN_A_5 17 /* pin1 */ #define PIN_A_6 11 /* pin7 */ #define PIN_A_7 16 /* pin2 */ #define PIN_A_8 13 /* pin5 */ #define PIN_K_1 6 /* pin13 */ #define PIN_K_2 15 /* pin3 */ #define PIN_K_3 14 /* pin4 */ #define PIN_K_4 3 /* pin10 */ #define PIN_K_5 12 /* pin6 */ #define PIN_K_6 4 /* pin11 */ #define PIN_K_7 8 /* pin15 */ #define PIN_K_8 9 /* pin16 */ // Pin 22,23,24 are assigned to RGB LEDs. int led_red = 22; // LOW active int led_green = 23; // LOW active int led_blue = 24; // LOW active unsigned char leddat[8]; int ledrow = 0; void dynamic_led(unsigned long u32ms); void disp_update(unsigned long u32ms); // the setup routine runs once when you press reset: void setup() { //setPowerManagementMode(PM_STOP_MODE, 0, 1023); //Set CPU STOP_MODE in delay() //setOperationClockMode(CLK_LOW_SPEED_MODE); //Set CPU clock from 32MHz to 32.768kHz memset( leddat, 0, sizeof(leddat) ); leddat[0] = 0x18; leddat[1] = 0x24; leddat[2] = 0x42; leddat[3] = 0x81; leddat[4] = 0x81; leddat[5] = 0x42; leddat[6] = 0x24; leddat[7] = 0x18; // initialize the digital pin as an output. Serial.begin(9600); pinMode(led_red, OUTPUT); pinMode(led_green, OUTPUT); pinMode(led_blue, OUTPUT); pinMode(PIN_A_1, OUTPUT); pinMode(PIN_A_2, OUTPUT); pinMode(PIN_A_3, OUTPUT); pinMode(PIN_A_4, OUTPUT); pinMode(PIN_A_5, OUTPUT); pinMode(PIN_A_6, OUTPUT); pinMode(PIN_A_7, OUTPUT); pinMode(PIN_A_8, OUTPUT); pinMode(PIN_K_1, OUTPUT); pinMode(PIN_K_2, OUTPUT); pinMode(PIN_K_3, OUTPUT); pinMode(PIN_K_4, OUTPUT); pinMode(PIN_K_5, OUTPUT); pinMode(PIN_K_6, OUTPUT); pinMode(PIN_K_7, OUTPUT); pinMode(PIN_K_8, OUTPUT); attachCyclicHandler(0, dynamic_led, 1); attachCyclicHandler(1, disp_update, 1000); // turn the LEDs on, glow white. digitalWrite(led_red, LOW); digitalWrite(led_green, LOW); digitalWrite(led_blue, LOW); } // the loop routine runs over and over again forever: void loop() { } // LED dynamic void dynamic_led(unsigned long u32ms) { unsigned char dt = leddat[ledrow]; /* LED */ digitalWrite( PIN_A_1, ( ledrow == 0 ) ? HIGH : LOW ); digitalWrite( PIN_A_2, ( ledrow == 1 ) ? HIGH : LOW ); digitalWrite( PIN_A_3, ( ledrow == 2 ) ? HIGH : LOW ); digitalWrite( PIN_A_4, ( ledrow == 3 ) ? HIGH : LOW ); digitalWrite( PIN_A_5, ( ledrow == 4 ) ? HIGH : LOW ); digitalWrite( PIN_A_6, ( ledrow == 5 ) ? HIGH : LOW ); digitalWrite( PIN_A_7, ( ledrow == 6 ) ? HIGH : LOW ); digitalWrite( PIN_A_8, ( ledrow == 7 ) ? HIGH : LOW ); if( ( dt & 0x80 ) == 0 ){ digitalWrite( PIN_K_1, HIGH ); } else{ digitalWrite( PIN_K_1, LOW ); } if( ( dt & 0x40 ) == 0 ){ digitalWrite( PIN_K_2, HIGH ); } else{ digitalWrite( PIN_K_2, LOW ); } if( ( dt & 0x20 ) == 0 ){ digitalWrite( PIN_K_3, HIGH ); } else{ digitalWrite( PIN_K_3, LOW ); } if( ( dt & 0x10 ) == 0 ){ digitalWrite( PIN_K_4, HIGH ); } else{ digitalWrite( PIN_K_4, LOW ); } if( ( dt & 0x08 ) == 0 ){ digitalWrite( PIN_K_5, HIGH ); } else{ digitalWrite( PIN_K_5, LOW ); } if( ( dt & 0x04 ) == 0 ){ digitalWrite( PIN_K_6, HIGH ); } else{ digitalWrite( PIN_K_6, LOW ); } if( ( dt & 0x02 ) == 0 ){ digitalWrite( PIN_K_7, HIGH ); } else{ digitalWrite( PIN_K_7, LOW ); } if( ( dt & 0x01 ) == 0 ){ digitalWrite( PIN_K_8, HIGH ); } else{ digitalWrite( PIN_K_8, LOW ); } if( ledrow == 7 ){ ledrow = 0; } else{ ledrow ++; } } void disp_update( unsigned long u32ms ) { int y, x; int num = 0; int alive = 0; unsigned char work[8]; for(y=0; y<8; y++){ work[y] = leddat[y]; } for(y=0; y<8; y++){ for(x=0; x<8; x++){ num = 0; /* count around */ if( x != 0 ){ if( ( ( leddat[y] >> ( 8-x ) ) & 0x01 ) != 0 ){ num ++; } } if( x != 7 ){ if( ( ( leddat[y] >> ( 6-x ) ) & 0x01 ) != 0 ){ num ++; } } if( y != 0 ){ if( ( ( leddat[y-1] >> ( 7-x ) ) & 0x01 ) != 0 ){ num ++; } if( x != 0 ){ if( ( ( leddat[y-1] >> ( 8-x ) ) & 0x01 ) != 0 ){ num ++; } } if( x != 7 ){ if( ( ( leddat[y-1] >> ( 6-x ) ) & 0x01 ) != 0 ){ num ++; } } } if( y != 7 ){ if( ( ( leddat[y+1] >> ( 7-x ) ) & 0x01 ) != 0 ){ num ++; } if( x != 0 ){ if( ( ( leddat[y+1] >> ( 8-x ) ) & 0x01 ) != 0 ){ num ++; } } if( x != 7 ){ if( ( ( leddat[y+1] >> ( 6-x ) ) & 0x01 ) != 0 ){ num ++; } } } /* decide */ if( ( ( leddat[y] >> ( 7-x ) ) & 0x01 ) == 0 ){ if( num == 3 ){ work[y] |= ( 0x80 >> x ); } } else{ if( ( num != 2 ) && ( num != 3 ) ){ work[y] &= ~( 0x80 >> x ); } } } } for( y=0; y<8; y++ ){ leddat[y] = work[y]; } }
一応、ライフゲームになってます。
参考:
GR KURUMI買いました
GR KURUMIを買いました。
買った状態だとIOどころかプログラム書き込み用のピンすら立っておらず、はんだ付け必須という、小さいですがなかなか硬派?なマイコンボードであります。
まだ、全然使いこなせていないのですが、とりあえずtone関数を使ったサンプルがあったので、参考にして「KissからはじまるMiracle」の冒頭を演奏させてみました。(みらくるみ、なので)
スケッチは以下です。
/*GR-KURUMI Sketch Template Version: V1.00*/ #include <RLduino78.h> // Pin 22,23,24 are assigned to RGB LEDs. int led_red = 22; // LOW active int led_green = 23; // LOW active int led_blue = 24; // LOW active #define TONE_C4 262 #define TONE_C4S 277 #define TONE_D4 294 #define TONE_D4S 311 #define TONE_E4 330 #define TONE_F4 349 #define TONE_F4S 370 #define TONE_G4 392 #define TONE_G4S 415 #define TONE_A4 440 #define TONE_A4S 466 #define TONE_B4 494 #define TONE_C5 523 #define TONE_C5S 554 #define TONE_D5 587 #define TONE_D5S 622 #define TONE_E5 659 #define TONE_F5 698 #define TONE_F5S 740 #define TONE_G5 784 #define TONE_G5S 831 #define TONE_A5 880 #define TONE_A5S 932 #define TONE_B5 988 #define TONE_C6 1047 #define TONE_C6S 1109 #define TONE_D6 1175 #define TONE_D6S 1245 #define TONE_E6 1319 #define TONE_F6 1397 #define TONE_F6S 1480 #define TONE_G6 1568 #define TONE_G6S 1661 #define TONE_A6 1780 #define TONE_A6S 1865 #define TONE_B6 1976 // the setup routine runs once when you press reset: void setup() { //setPowerManagementMode(PM_STOP_MODE, 0, 1023); //Set CPU STOP_MODE in delay() //setOperationClockMode(CLK_LOW_SPEED_MODE); //Set CPU clock from 32MHz to 32.768kHz // initialize the digital pin as an output. pinMode(led_red, OUTPUT); pinMode(led_green, OUTPUT); pinMode(led_blue, OUTPUT); pinMode(5, OUTPUT); // turn the LEDs on, glow white. digitalWrite(led_red, LOW); digitalWrite(led_green, LOW); digitalWrite(led_blue, LOW); // play tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_F5S); delay(182); noTone(5); delay(10); tone(5, TONE_F5S); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_A5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_F5S); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(375); noTone(5); delay(10); delay(577); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_F5S); delay(182); noTone(5); delay(10); tone(5, TONE_F5S); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_B5); delay(182); noTone(5); delay(10); tone(5, TONE_A5); delay(182); noTone(5); delay(10); tone(5, TONE_B5); delay(182); noTone(5); delay(10); tone(5, TONE_A5); delay(375); noTone(5); delay(10); delay(577); tone(5, TONE_B5); delay(182); noTone(5); delay(10); tone(5, TONE_B5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_E5); delay(182); noTone(5); delay(10); tone(5, TONE_E5); delay(182); noTone(5); delay(10); tone(5, TONE_D5); delay(182); noTone(5); delay(10); tone(5, TONE_D5); delay(182); noTone(5); delay(10); tone(5, TONE_B5); delay(182); noTone(5); delay(10); tone(5, TONE_B5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_G5); delay(182); noTone(5); delay(10); tone(5, TONE_E5); delay(182); noTone(5); delay(10); tone(5, TONE_E5); delay(182); noTone(5); delay(10); tone(5, TONE_D5); delay(182); noTone(5); delay(10); tone(5, TONE_D5); delay(182); noTone(5); delay(10); tone(5, TONE_E5); delay(182); noTone(5); delay(10); delay(192); tone(5, TONE_E5); delay(182); noTone(5); delay(10); delay(192); tone(5, TONE_F5S); delay(182); noTone(5); delay(10); tone(5, TONE_F5S); delay(182); noTone(5); delay(10); delay(192); tone(5, TONE_G5); delay(375); noTone(5); delay(10); delay(577); } // the loop routine runs over and over again forever: void loop() { }
…ただの力技ですね。
単音なのが寂しいですが、DACつけたら和音鳴るような気もします。今後の課題ということで…。
部品は圧電サウンダのみです。IO5とGNDに圧電サウンダをつなげました。
参考:
KURUMIでキーボードピアノ(toneのお試し) - がじぇっとるねさす ゆーざー会 - Blog - がじぇっとるねさすゆーざー会 - Renesas Rulz - Japan
圧電スピーカー(圧電サウンダ)(22mm)PKM22EPPH2001−B0: パーツ一般 秋月電子通商 電子部品 ネット通販
Raspberry PiとGR SAKURAでキャラクターLCD (2)
Raspberry Pi側からGR SAKURAに対して、自分のIPアドレスを文字列としてUARTに流すのですが、出荷時の設定だとUARTはシリアルターミナルのログイン用になっており、通信に使用できないとのことで、起動設定を変更しました。
変更内容は下記サイトの内容そのままです。
Raspberry Pi でシリアル通信 Chick Lab
書いてあるとおりに、以下の2ファイルを変更しました。
/boot/cmdline.txt
/etc/inittab
また、シリアル通信を一から書くと意外と面倒ですので、WiringPiというライブラリーを入れます。
公式サイト:Raspberry Pi | Wiring | Gordons Projects
インストールは上記のサイトの以下のページの通りにすすめます。
Raspberry Pi | Wiring | Download & Install | Gordons Projects
(うちは最初のgit-coreのインストールでエラーが出たので、updateとupgradeを行いましたが、けっこう時間がかかりました…)
WiringPiをインストールすると、serialXXXXという名前のついた関数を使って簡単にシリアル通信ができるようになります。
以下がRaspberry Pi側のプログラムです。
/* ipuart.c */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> #include <wiringSerial.h> /* WiringPi */ int main( int ac, char *av[] ) { int fd, sfd; struct ifreq ifr; char ipstr[256]; /* get my IP addr */ fd = socket(AF_INET, SOCK_DGRAM, 0); ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1); ioctl(fd, SIOCGIFADDR, &ifr ); close(fd); memset( ipstr, '\0', sizeof(ipstr)); strcpy(ipstr, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); // printf("%s\n", ipstr); /* UART */ sfd = serialOpen( "/dev/ttyAMA0", 38400 ); if( sfd == -1 ){ printf( "serial cannot open.\n" ); return 1; } serialPuts( sfd, ipstr ); delay(1000); serialClose( sfd ); return 0; }
(前半でソケットを使ってマジメにIPアドレスを取得していますが、実はこの処理は不要なことが後で判明…)
ビルドすると実行ファイルができるので適当なディレクトリに置きます。うちは、/usr/local/binに置いてみました。
あとは、起動時に実行するようにしたいので、/etc/rc.localの末尾に実行ファイル名を書いておきます。以下は記述例です。
/usr/local/bin/ipuart
(上でIP取得が不要と書いた理由ですが、rc.localの中で自分のIPアドレスが$_IPという変数に記録されていますので、引数に指定した文字列をそのままUARTに流すようなプログラムを作れば$_IPを引数にするだけでよくなります。結果、自作プログラムの中でIPを取得する必要は無くなります…。)
ただ、GR SAKURAを持ち出したり、20x4という大きめのLCDを使っていたりと、我ながらIP表示するだけのことにずいぶんおおげさになってしまったなあと思いまして、結局、今は3.3VでI2Cインタフェースの小さい16x2 LCDを直接Raspberry Piにつないでおります。まあ、勉強にはなりましたので後悔はしてません。多分…。