다중 디스플레이 지원( Display 생성부분이 완전이 새로워짐)
다중 디스플레이를 위한 블루투스 연결은 하드웨어 시리얼과 소프트웨어 시리얼이 있음
Display Class는 모두 지원하고 생성자도 함수 오버레이로 동일한 형태임
기존 #define문은 사라지고 생성시 바로 시리얼 주소을 넘겨주면 됨
#include <SoftwareSerial.h> // 소프트웨어 시리얼 사용시만
SoftwareSerial Soft(A1, A0); //( Rx, Tx )
Display hp( &Serial ); // 하드웨어 시리얼의 주소를 넘겨준다 ( Mega는 4개까지 사용가능 )
Display sp( &Soft ); // 소프트웨어 시리얼 주소를 넘겨준다
hp.begin( 115200 )
sp.begin( 115200 ); // 소프트웨어 시리얼은 원활한 작동을 위해 속도 조절 필요
hp.display(); // Timer루프에서 빠져나와 화면에 그래픽을 보여준다.
sp.display(); // 기존 echo()함수는 응답 대기에만 사용( 다른 디스플레이도 중단 시키므로)
일반적인 수학좌표계로 그래픽을 코딩 할 수 있는 기능을 추가 했다.
새로운 함수들은 기존 디바이스 좌표계함수에 c를 더하면 된다.
먼저 원점을 설정한다. 디바이스의 중심을 원점으로 한다면
setCenter( 디바이스 너비 /2, 디바이스 높이 /2 )로 코딩하면 된다.
좌표계는 위의 그림처럼 바뀐다. (0,0)에서 (3,5)까지 선을 그린다면
cLine( 0,0 ,3,5)라고 코딩하면 된다. 따로 좌표 변환이 필요없다.
참고로 line(0,0,3,5)는 기존 디바이스 좌표계 그리기 함수다.
아래의 새로운 앱을 다운 받아야 사용 가능 하다.
추가 또는 변경된 함수목록
메소드 | 기능 |
void begin( long speed ) | 시리얼을 속도를 세팅하여 시작하기 |
void display() | Timer루프에서 빠져나와 화면에 그래픽을 보여준다.( 다른 디스플레이와 무관) |
void echo(); | 신호를 보내고 응답을 기다림 / 모든 연결된 디스플레이 장치가 중단됨 |
void getSize() | 너비,높이를 얻어 Class변수 w, h에 저장함 |
int getWidth(); | 너비 |
int getHeight(); | 높이 |
void tick( byte _t ) | 그리기 선의 두께 설정 |
void color(unsigned long c) | 그리기 색 설정 |
void bkColor(unsigned long c) | 배경색 설정 |
void textSize( int s); | 텍스트 크기 설정 |
void textAt( byte a) | 텍스트 정열 설정 Left 0 Mid 1 Right 2 |
정열을 다른 방식으로 | void atext() 완쪽정열 void texta() 오른쪽정열 void atexta() 가운데 정열 |
void text( int x, int y, String msg) | 텍스트 그리기 |
void cText( int x, int y, String msg) | 수학 좌표 |
void save(String name) | 캔버스 이미지 저장 "/Sample.png" |
void load(String name) | 배경 이미지 불러오기 path+"Sample.png" |
앱인벤트 웹에서 AI로 사용시 path | "/storage/emulated/0/Android/data/edu.mit.appinventor.aicompanion3/files/" |
APK로 설치후 사용시 path | "/storage/emulated/0/Android/data/appinventor.ai_구글ID.Display/files/" |
void setCenter( int x, int y) | 원점 설정 |
int dx( int x) | 디바이스 x좌표를 수학 x좌표로 변환 |
int dy( int y) | 디바이스 y좌표를 수학 y좌표로 변환 |
int rxy( int x ,int r) | X^2 + Y^2 =R^2 원의 공식으로 x,y좌표로 반지름 r 원주상의 y,x좌표를 구함 |
void pixel( int x, int y) | 점 그리기 |
void cPixel( int x, int y) | |
unsigned long getPixel(int x, int y) | 해당 좌표 점 색상 얻기 |
unsigned long cGetPixel(int x, int y) | |
void line( int x, int y, int x2, int y2) | 선그리기 |
void cLine( int x, int y, int x2, int y2) | |
void rec( int x, int y, int x2, int y2) | 사각형 그리기 |
void rec( int x, int y, int x2, int y2,bool f) | true면 꽉찬 사각형 |
void cRec( int x, int y, int x2, int y2) | |
void cRec( int x, int y, int x2, int y2,bool f) | |
void circle( int x, int y, int r) | 원그리기 |
void circle( int x, int y, int r, bool f) | true면 꽉찬 원 |
void cCircle( int x, int y, int r) | |
void cCircle( int x, int y, int r, bool f) | |
void arc( int x, int y, int x2, int y2, int start, int sweep, bool center , bool fill) 원호 그리기 |
|
void cArc( int x, int y, int x2, int y2, int start, int sweep, bool center , bool fill) |
새로운 블루투스 디스플레이 Display.H | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Display Class : 블루투스로 연결된 안드로이드 휴대폰, 탭을 아두이노에서 디스플레이로 활용하기
//
// 작성자 : okjin-shin.tistory.com 2022.09.06 ver 2.0
//
// 재배포 금지 : 링크를 사용 하세요. MultiDisplay가능판 , 호환앱이 필요함
// 개별적 수정사용 가능
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _Display_
#define _Display_
#include "ARGB_COLOR.H"
class Display
{
private :
int center_x = 0; // 원점의 디바이스 좌표
int center_y = 0;
bool Soft = false; // 이 객체가 소프트웨어 시리얼이면 true
HardwareSerial *_BT; // 하드웨어 시리얼 객체
#ifdef SoftwareSerial_h // 소프트시리얼 사용시만
SoftwareSerial *_ST; // 소프트웨어 시리얼 객체
#endif
public:
int w = 0 ; // 화면 너비
int h = 0 ; // 화면 높이
Display( HardwareSerial *hSerial){ _BT=hSerial;} // 하드웨어시리얼시 생성자
#ifdef SoftwareSerial_h
Display( SoftwareSerial *sSerial){ _ST=sSerial; Soft=true; } // 소프트웨어 시리얼시 생성자
#endif
int dx( int x){ return x+center_x; } // 좌표를 디바이스좌표로 변환
int dy( int y){ return( h-(y+h/2) ); }
int rxy( int x ,int r){ return sqrt( r*r - x*x ) ; } // 원주상의 좌표를 반환 x->y y->x를 반환
void echo();
void begin(long speed );
void display();
void getSize(){ w=getWidth(); h=getHeight(); }
void clear();
void color(unsigned long c);
void bkColor(unsigned long c);
int getWidth();
int getHeight();
void tick( byte _t );
void circle( int x, int y, int r, bool f);
void circle( int x, int y, int r) { circle( x, y, r, false); }
void cCircle( int x, int y, int r, bool f) { circle( dx(x), dy(y), r, f); }
void cCircle( int x, int y, int r) { circle( dx(x), dy(y), r, false); }
void arc( int x, int y, int x2, int y2, int start, int sweep, bool center , bool fill);
void cArc( int x, int y, int x2, int y2, int start, int sweep, bool center , bool fill){arc( dx(x), dy(y), dx(x2), dy(y2), start, sweep, center , fill);}
void line( int x, int y, int x2, int y2);
void cLine( int x, int y, int x2, int y2){ line( dx(x), dy(y), dx(x2), dy(y2) ); }
void rec( int x, int y, int x2, int y2,bool f);
void rec( int x, int y, int x2, int y2){ rec( x, y, x2, y2, false); }
void cRec( int x, int y, int x2, int y2,bool f){ rec( dx(x), dy(y), dx(x2), dy(y2), f); }
void cRec( int x, int y, int x2, int y2){ cRec( x, y, x2, y2, false); }
void pixel( int x, int y);
void cPixel( int x, int y){ pixel( dx(x), dy(y) ); }
unsigned long getPixel(int x, int y);
unsigned long cGetPixel(int x, int y){ getPixel( dx(x), dy(y) ); }
void text( int x, int y, String msg);
void cText( int x, int y, String msg){ text( dx(x), dy(y), msg); }
void textSize( int s);
void textAt( byte a); // Left 0 Mid 1 Right 2
void atext(){ textAt(0); }
void texta(){ textAt(2); }
void atexta(){ textAt(1); }
void save(String name);
void load(String name);
void setCenter( int x, int y){ center_x = x; center_y =y; }
private:
void send2Byte( int n ){ _BT->write( lowByte(n) ); _BT->write( highByte(n) ); }
#ifdef SoftwareSerial_h
void sSend2Byte( int n){ _ST->write( lowByte(n) ); _ST->write( highByte(n) ); }
#endif
};
void Display::begin( long speed )
{
#ifdef SoftwareSerial_h
if( Soft ) _ST->begin(speed);
else
#endif
_BT->begin( speed );
}
void Display::echo()
{
byte b;
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('e');
while( ! _ST->available())
_ST->readBytes(&b,1);
}else
#endif
{
_BT->write('e');
while( ! _BT->available())
_BT->readBytes(&b,1);
}
}
void Display::display()
{
#ifdef SoftwareSerial_h
if( Soft ) _ST->write('D');
else
#endif
_BT->write('D');
}
void Display::tick( byte _t)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('t');
_ST->write(_t);
}
else
#endif
{
_BT->write('t');
_BT->write(_t);
}
}
int Display::getWidth()
{
int i;
byte buff[2];
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('W');
while( ! _ST->available() ){}
_ST->readBytes(buff,2);
}
else
#endif
{
_BT->write('W');
while( ! _BT->available() ){}
_BT->readBytes(buff,2);
}
i= buff[0]+buff[1]*0x100;
w=i;
return i;
}
int Display::getHeight()
{
int i;
byte buff[2];
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('H');
while( ! _ST->available() ){}
_ST->readBytes(buff,2);
}
else
#endif
{
_BT->write('H');
while( ! _BT->available() ){}
_BT->readBytes(buff,2);
}
i= buff[0]+buff[1]*0x100;
h=i;
return i;
}
void Display::save(String name)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('s');
sSend2Byte( name.length() );
_ST->println( name);
}
else
#endif
{
_BT->write('s');
send2Byte( name.length() );
_BT->println( name);
}
}
void Display::load(String name)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('l');
sSend2Byte( name.length() );
_ST->println( name);
}
else
#endif
{
_BT->write('l');
send2Byte( name.length() );
_BT->println( name);
}
}
void Display::clear()
{
#ifdef SoftwareSerial_h
if( Soft ) _ST->write('Z');
else
#endif
_BT->write('Z');
}
unsigned long Display::getPixel(int x, int y)
{
unsigned long c=0;
byte buff[4];
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('G');
sSend2Byte(x);
sSend2Byte(y);
while( ! _ST->available() ){}
_ST->readBytes(buff,4);
} else
#endif
{
_BT->write('G');
send2Byte(x);
send2Byte(y);
while( ! _BT->available() ){}
_BT->readBytes(buff,4);
}
c= buff[0]+buff[1]*0x100+buff[2]*0x10000+buff[3]*0x1000000;
return c;
}
void Display::textAt( byte a)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('A');
_ST->write(a);
} else
#endif
{
_BT->write('A');
_BT->write(a);
}
}
void Display::textSize( int s)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('S');
sSend2Byte(s);
} else
#endif
{
_BT->write('S');
send2Byte(s);
}
}
void Display::text( int x, int y, String msg)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('T');
sSend2Byte( msg.length() );
sSend2Byte( x );
sSend2Byte( y );
_ST->println(msg);
}else
#endif
{
_BT->write('T');
send2Byte( msg.length() );
send2Byte( x ) ;
send2Byte( y ) ;
_BT->println(msg);
}
}
void Display::pixel( int x, int y)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('P');
sSend2Byte( x ) ;
sSend2Byte( y );
}else
#endif
{
_BT->write('P');
send2Byte( x ) ;
send2Byte( y );
}
}
void Display::color(unsigned long c)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('c');
sSend2Byte( c &0xffff ) ;
sSend2Byte( (c>>16) &0xffff );
}else
#endif
{
_BT->write('c');
send2Byte( c &0xffff ) ;
send2Byte( (c>>16) &0xffff );
}
}
void Display::bkColor(unsigned long c)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('b');
sSend2Byte( c &0xffff ) ;
sSend2Byte( (c>>16) &0xffff );
}else
#endif
{
_BT->write('b');
send2Byte( c &0xffff ) ;
send2Byte( (c>>16) &0xffff );
}
}
void Display::circle( int x, int y, int r, bool f)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('C');
sSend2Byte( x );
sSend2Byte( y );
sSend2Byte( r );
_ST->write( f );
}else
#endif
{
_BT->write('C');
send2Byte( x );
send2Byte( y );
send2Byte( r );
_BT->write( f );
}
}
void Display::arc( int x, int y, int x2, int y2, int start, int sweep, bool center , bool fill)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('a');
sSend2Byte( x );
sSend2Byte( y );
sSend2Byte( x2 );
sSend2Byte( y2 );
sSend2Byte( start);
sSend2Byte( sweep );
_ST->write( center);
_ST->write( fill );
}else
#endif
{
_BT->write('a');
send2Byte( x );
send2Byte( y );
send2Byte( x2 );
send2Byte( y2 );
send2Byte( start);
send2Byte( sweep );
_BT->write( center);
_BT->write( fill );
}
}
void Display::line( int x, int y, int x2, int y2)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('L');
sSend2Byte( x );
sSend2Byte( y );
sSend2Byte( x2 );
sSend2Byte( y2);
}else
#endif
{
_BT->write('L');
send2Byte( x );
send2Byte( y );
send2Byte( x2 );
send2Byte( y2);
}
}
void Display::rec( int x, int y, int x2, int y2,bool f)
{
#ifdef SoftwareSerial_h
if( Soft )
{
_ST->write('R');
sSend2Byte( x );
sSend2Byte( y );
sSend2Byte( x2 );
sSend2Byte( y2);
_ST->write( f );
}else
#endif
{
_BT->write('R');
send2Byte( x );
send2Byte( y );
send2Byte( x2 );
send2Byte( y2);
_BT->write( f );
}
}
#endif
|
Sample Arduino Code | |
#include <SoftwareSerial.h> SoftwareSerial Soft(A1, A0); //( Rx, Tx ) #include "D:\\myHeader\\Display.H" #define _APK_ #ifdef _APK_ String path="/storage/emulated/0/Android/data/appinventor.ai_구글ID.Display/files/"; //설치된 앱의 위치 String path="/storage/emulated/0/Android/data/edu.mit.appinventor.aicompanion3/files/"; #endif Display hp( &Serial ); Display sp( &Soft ); int x=-130,d=1; bool ct=true; void setup() { hp.begin( 115200 ) sp.begin( 115200 ); // 소프트웨어 시리얼은 원활한 작동을 위해 속도 조절 필요 hp.echo(); // sp도 응답시까지 대기 hp.load(""); sp.load(""); hp.bkColor(MediumBlue); sp.bkColor(Blue); hp.getSize(); hp.atexta(); // 중앙정열 hp.textSize(40); hp.color(White); hp.text(hp.w/2,100,"블루투스 디스플레이"); hp.textSize(20); hp.color(Red); hp.text(hp.w/2,150,"Display.H Demo"); hp.color(White); hp.text(hp.w/2,200,"okjin-shin.tistory.com"); hp.save("/bk.png"); } void loop() { for( int cx=0; cx< hp.w ;cx+=30 ) { hp.getSize(); hp.setCenter(cx,100); //원점지정 -- 원점이 오른쪽으로 이동 hp.load( path+ "bk.png" ); hp.clear(); hp.color(Yellow); hp.cText( 0,0,"(0,0)"); // 원점을 기준으로한 수학좌표 그리기 함수는 c로 시작한다. hp.tick(1); hp.line( 0, hp.dy(0), hp.w, hp.dy(0)); // 한번 getSize()를 호출하면 w,h에 값이 저장되어 있음 hp.line(hp.dx(0),0, hp.dx(0), hp.h ); hp.tick(10); hp.cCircle( 0, 0, 130); int yy=hp.rxy(x,130)*d; hp.color(Red); hp.cLine(x,yy,-x,-yy); hp.color(Yellow); hp.cCircle( x , yy , 15 ,true); hp.color(Green); hp.cCircle( -x ,-yy, 15,true); hp.display(); x=x+30*d; if( x >130 ){ x=130; d= -1; } if( x <-130 ) { x=-130; d=1; } if(ct) sp.color(White); else sp.color(Red); ct = !ct; for( int r=0; r<150;r+=20) sp.circle(200,200,r); sp.display(); } } |
'프로젝트 > 휴대폰을 디스플레이로 활용하기' 카테고리의 다른 글
echo()사용 위치에 따른 그래픽 속도와 표현 차이 (0) | 2022.09.04 |
---|---|
기능 개선판 아두이노 Bluetooth Display (0) | 2022.09.03 |
앱인벤트로 라이브러리에 대응하는 블럭 만들기. (0) | 2022.08.27 |
휴대폰 디스플레이 라이브러리 클래스 (0) | 2022.08.27 |
그래픽 시연 (0) | 2022.08.26 |