SanguinoにLCD(SG12864)を接続してみた


最近Arduinoしてるんですが、元祖のDiecimilaはちょっとピン数が少ない。MEGAを使えばいいのだけれどもMEGAは高い。
そんななか、twitterでSanguinoというのを教えてもらったので、ATmega 644PというAVRを使ったSanguinoで色々遊んでみています。

作りたいものがあって、とりあえず液晶を接続してみようということで、接続してみました。
秋月電子のSG12864Aというのが、サイズがそこそこあって良いだろうということで買ってきてあったのですが、さすがArduino、既に接続した先人がいました。SG12864Aは128×64ピクセルのモノクロ液晶で、KS0108というコントローラを使ってみるみたいです。


コントローラのライブラリは、KS0108 Graphics LCD libraryというものです。が、作者さんがGLCD_Library_Beta1_2.zipという新しいバージョンを公開していらっしゃるので、こちらを使った方が良さそうです。

SanguinoとSG12864Aはこんな感じで繋ぎました。

あとは、上記ライブラリのzipを解凍するとks0108というフォルダが出来上がるので、自分のスケッチのフォルダの中にlibrariesフォルダを作って、その中に入れておきました。(Arduino-0017から出来るようになったそうです。)
あとは、ちょっとライブラリのコードを修正しました。(ついでに気になった点も直しました。)

ks0108.h
// Sanguinoは、ATmega644Pのはず。
//#elif defined (__AVR_ATmega644__)  // TODO - check this define 
#elif defined (__AVR_ATmega644P__)  // TODO - check this define </code></pre>
ks0108_Sanguino.h
/*******************************************************************************************/
/* Sanguino/ ATmega644 defines                                                             */
/*******************************************************************************************/
// Command pins assignments:
#define CSEL1				20 		// CS1 Bit   // swap pin assignments with CSEL2 if left/right image is reversed
#define CSEL2				19 		// CS2 Bit
#define R_W					18 		// R/W Bit
#define D_I					17 		// D/I Bit 
#define EN					16 		// EN Bit
//#define RESET				18 		// EN Bit

//all command pins are on the same port for slight speed & code size improvement
#define LCD_CMD_PORT		PORTC		// Command Output Register for pins 16-23

// data pin assignments- on ATmega644 all data pins are assigned to the same port
//#define dataPins0to7    // bits 0-7 assigned to sanguino pins 0-7
//#define dataPins8to15   // bits 0-7 assigned to sanguino pins 8-15 // note this conflicts with serial UART
//#define dataPins16to23  // bits 0-7 assigned to sanguino pins 16-23 
#define dataPins24to31  // bits 0-7 assigned to sanguino pins 24-31

基板も作りかけたのですが、最初、Sanguinoのpinの書き方を間違えていて動かず試行錯誤していたため、ブレッドボードで動作を確認しました。
動作確認に使ったスケッチは、こんな感じです。

SG12864_test.pde

#include <Arial14.h> // font definitions
#include <SystemFont5x7.h> // from example
#include <TestPattern.h>
#include <ks0108.h> // from example
#include <ks0108_Panel.h>

/*
* GLCDexample
*
* Basic test code for the Arduino KS0108 GLCD library.
* This code exercises a range of graphic functions supported
* by the library and is an example of its use.
* It also gives an indication of performance, showing the
* number of frames drawn per second.
*/

unsigned long startMillis;
unsigned int loops = 0;
unsigned int iter = 0;

void setup(){
GLCD.Init(NON_INVERTED); // initialise the library, non inverted writes pixels onto a clear screen
GLCD.ClearScreen();
introScreen(); // show some intro stuff
GLCD.ClearScreen();
}

void introScreen(){
GLCD.SelectFont(Arial_14); // you can also make your own fonts, see playground for details
GLCD.GotoXY(20, 2);
GLCD.Puts(“GLCD version 1.1”);
GLCD.DrawRoundRect(16,0,99,18, 5, BLACK); // rounded rectangle around text area

GLCD.SelectFont(System5x7); // switch to fixed width system font
showCharacters();

for(byte count=9; count >0; count–){ // do countdown
GLCD.CursorTo(0,1); // first column, seconds row (offset is from 0)
GLCD.PutChar(count + ‘0’);
delay(1000);
}
}

void showCharacters(){
byte line = 3; // start on the fourth line
for(byte c = 32; c <=127; c++){ if( (c-32) % 20 == 0) GLCD.CursorTo(1,line++); // CursorTo is used for fixed width system font GLCD.PutChar(c); } } void drawSpinner(byte pos, byte x, byte y) { // this draws an object that appears to spin switch(pos % 8) { case 0 : GLCD.DrawLine( x, y-8, x, y+8, BLACK); break; case 1 : GLCD.DrawLine( x+3, y-7, x-3, y+7, BLACK); break; case 2 : GLCD.DrawLine( x+6, y-6, x-6, y+6, BLACK); break; case 3 : GLCD.DrawLine( x+7, y-3, x-7, y+3, BLACK); break; case 4 : GLCD.DrawLine( x+8, y, x-8, y, BLACK); break; case 5 : GLCD.DrawLine( x+7, y+3, x-7, y-3, BLACK); break; case 6 : GLCD.DrawLine( x+6, y+6, x-6, y-6, BLACK); break; case 7 : GLCD.DrawLine( x+3, y+7, x-3, y-7, BLACK); break; } } void loop(){ // run over and over again iter = 0; startMillis = millis(); while( millis() - startMillis < 1000){ // loop for one second GLCD.DrawRect(0, 0, 64, 61, BLACK); // rectangle in left side of screen GLCD.DrawRoundRect(68, 0, 58, 61, 5, BLACK); // rounded rectangle around text area for(int i=0; i < 62; i += 4) GLCD.DrawLine(1,1,63,i, BLACK); // draw lines from upper left down right side of rectangle GLCD.DrawCircle(32,31,30,BLACK); // draw circle centered in the left side of screen GLCD.FillRect(92,40,16,16, WHITE); // clear previous spinner position drawSpinner(loops++,100,48); // draw new spinner position //GLCD.FillRect(24,txtLINE3,14,14, WHITE); // clear text area that will be drawn below GLCD.CursorTo(5,5); // locate curser for printing text GLCD.PrintNumber(++iter); // print current iteration at the current cursor position } // display number of iterations in one second GLCD.ClearScreen(); // clear the screen GLCD.CursorTo(14,2); // positon cursor GLCD.Puts("FPS= "); // print a text string GLCD.PrintNumber(iter); // print a number } int main() { init(); setup(); for(;;) loop(); return 0; } [/cpp]