128*64白黒液晶にPC画面を転送
秋月で売っている128*64液晶とarduinoをつないでPC画面をキャプチャしたデータを表示しています.ところどころ,転送漏れしてます...
回路の方は http://q61.org/chibimo/ こちらの方の回路をそのまま使わせていただいて,
ソフトは頑張って書いてみました.一応,pure arduino languageです.直接レジスタいじったりしていません(スキルがないだけ).
PyGTK→Python→serial→Arduino→SG12864
arduino スケッチ
class GraphicLcd{ public: struct Status { int busy; int on_off; int reset; } status; GraphicLcd(int di, int rw, int e, int res, int cs1, int cs2, int db0, int db1, int db2, int db3, int db4, int db5, int db6, int db7); void displayOnOFF(int on_off); void displayStartLine(int line); void setPageAddress(int page); void setColumnAddress(int column); void setChip(int chip); void statusRead(void); void writeDisplay(int data); int readDisplay(void); private : int di_pin; int rw_pin; int e_pin; int res_pin; int cs1_pin; int cs2_pin; int _data_pins[8]; int _data; int di; int rw; int chip; void enable(void); void setData(void); void getData(void); int strToData(const char *string); }; GraphicLcd::GraphicLcd(int di_pin, int rw_pin, int e_pin, int res_pin, int cs1_pin, int cs2_pin, int db0, int db1, int db2, int db3, int db4, int db5, int db6, int db7) { this->di_pin = di_pin; this->rw_pin = rw_pin; this->e_pin = e_pin; this->res_pin = res_pin; this->cs1_pin = cs1_pin; this->cs2_pin = cs2_pin; _data_pins[0] = db0; _data_pins[1] = db1; _data_pins[2] = db2; _data_pins[3] = db3; _data_pins[4] = db4; _data_pins[5] = db5; _data_pins[6] = db6; _data_pins[7] = db7; pinMode(di_pin, OUTPUT); pinMode(rw_pin, OUTPUT); pinMode(e_pin, OUTPUT); pinMode(res_pin, OUTPUT); pinMode(cs1_pin, OUTPUT); pinMode(cs2_pin, OUTPUT); for(int i = 0; i < 8; i++){ pinMode(_data_pins[i], OUTPUT); digitalWrite(_data_pins[i], HIGH); } digitalWrite(e_pin, LOW); digitalWrite(di_pin, LOW); digitalWrite(rw_pin, LOW); digitalWrite(res_pin, HIGH); digitalWrite(cs1_pin, LOW); digitalWrite(cs2_pin, LOW); } void GraphicLcd::enable(void) { digitalWrite(di_pin, di); digitalWrite(rw_pin, rw); if(chip%2 == 0){ digitalWrite(cs1_pin, LOW); digitalWrite(cs2_pin, HIGH); } else{ digitalWrite(cs1_pin, HIGH); digitalWrite(cs2_pin, LOW); } setData(); digitalWrite(e_pin, HIGH); digitalWrite(e_pin, LOW); } void GraphicLcd::setData(void) { for(int i = 0; i < 8; i++){ digitalWrite(_data_pins[i], (_data>>i)&1); } } void GraphicLcd::getData(void) { _data = 0; for(int i = 0; i < 8; i++){ _data |= (digitalRead(_data_pins[i])<<i); } } int GraphicLcd::strToData(const char *string) { int data = 0; for(int i = 0; i < 8; i++){ data <<= 1; data += string[i]=='1'?1:0; } return data; } void GraphicLcd::displayOnOFF(int on_off) { di = LOW; rw = LOW; _data = strToData("00111110"); _data |= on_off; enable(); } void GraphicLcd::displayStartLine(int line) { di = LOW; rw = LOW; _data = strToData("11000000"); _data |= line; enable(); } void GraphicLcd::setPageAddress(int page) { di = LOW; rw = LOW; _data = strToData("10111000"); _data |= page; enable(); } void GraphicLcd::setColumnAddress(int column) { di = LOW; rw = LOW; _data = strToData("01000000"); _data |= column; enable(); } void GraphicLcd::statusRead(void) { di = LOW; rw = HIGH; _data = strToData("00000000"); enable(); getData(); status.busy = (_data>>7)&1; status.on_off = (_data>>5)&1; status.reset = (_data>>4)&1; } void GraphicLcd::writeDisplay(int data) { di = HIGH; rw = LOW; _data = data; enable(); } int GraphicLcd::readDisplay() { di = HIGH; rw = HIGH; enable(); getData(); return _data; } void GraphicLcd::setChip(int chip) { this->chip = chip; } GraphicLcd glcd(17, 18, 19, 13, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9); #define BUFFER_SIZE 1024+512 unsigned char buf[BUFFER_SIZE]; int sbufp, ebufp; int i, j; void glcd_write(int i, int j, int data) { glcd.setChip(1-j/64); glcd.setPageAddress(i); glcd.setColumnAddress(j%64); glcd.writeDisplay(data); } void setup(void) { glcd.displayStartLine(0xC0); glcd.setChip(0); glcd.displayOnOFF(1); glcd.setChip(1); glcd.displayOnOFF(1); Serial.begin(57600); sbufp = 0; ebufp = 0; } void loop(void) { while(Serial.available()&&!(ebufp-sbufp >= BUFFER_SIZE-1 || (ebufp+(BUFFER_SIZE-sbufp) >= BUFFER_SIZE-1 && ebufp < sbufp))){ buf[ebufp++] = Serial.read(); if(!(ebufp-BUFFER_SIZE)) ebufp = 0; } if(ebufp-sbufp >= 3 || (ebufp+(BUFFER_SIZE-sbufp) >= 3 && ebufp < sbufp)){ i = buf[sbufp++]; if(!(ebufp-BUFFER_SIZE)) ebufp = 0; if(8<=i) return; j = buf[sbufp++]; if(!(ebufp-BUFFER_SIZE)) ebufp = 0; glcd_write(i,j,buf[sbufp++]); if(!(ebufp-BUFFER_SIZE)) ebufp = 0; } }
PC側プログラム
#!/usr/bin/env python # -*- coding: utf-8 -*- import pygtk import gtk import time import threading import gobject import sys class graphicsLCD: def __init__(self, scale=1): self.scale = scale self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_size_request(128*self.scale, 0) self.window.show() self.window.connect("event", self.get_coordinates) self.x = 0 self.y = 0 self.disp_array = [[0 for j in range(128)] for i in range(64)]; self.temp_array = [[0 for j in range(128)] for i in range(64)]; gobject.timeout_add(1, self.timeout) def main(self): gtk.main() def get_coordinates(self, widget, event) : " ウインドウ座標取得 " (self.x, self.y) = self.window.get_position() def timeout(self): " キャプチャ " root = gtk.gdk.get_default_root_window() pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 128*self.scale, 64*self.scale) pixbuf.get_from_drawable(root, gtk.gdk.colormap_get_system(), self.x, self.y+30, 0, 0, 128*self.scale, 64*self.scale) pixels = pixbuf.get_pixels() " グレースケール化 " for i in range(64): for j in range(128): self.temp_array[i][j] =( (ord(pixels[i*self.scale*128*self.scale*3+j*self.scale*3])*0.298912 +ord(pixels[i*self.scale*128*self.scale*3+j*self.scale*3+1])*0.586611 +ord(pixels[i*self.scale*128*self.scale*3+j*self.scale*3+2])*0.114478)) " しきい値(平均を求める) " sum = 0 for i in range(64): for j in range(128): sum += self.temp_array[i][j] siki = sum/(64*128) " 二値化 " array = [[0 for j in range(128)] for i in range(64)]; for i in range(64): for j in range(128): if self.temp_array[i][j] > siki : array[i][j] = 0 else : array[i][j] = 1 " 転送 " f = open('/dev/ttyUSB0', 'w'); for i in range(8): for j in range(128): reDrawFlag = False data = 0 for k in range(8): if self.disp_array[8*i+k][j] != array[8*i+k][j] : reDrawFlag = True data += (array[8*i+k][j])*2**k " データに変更があったときのみ転送 " if reDrawFlag == True : f.write("%c%c%c" % (chr(i), chr(j), chr(data))) # time.sleep(0.000008) # for i in range(64): # for j in range(128): # if array[i][j] == 0: # sys.stdout.write(' ') # else : # sys.stdout.write('*') # print # print "--send data--" # time.sleep(0.01) self.disp_array = array gobject.timeout_add(1, self.timeout) print __name__ if __name__ == "__main__": glcd = graphicsLCD(4) glcd.main()