진짜를 만들어보자 - 4. RTC 모듈 연결과 LCD 출력


지난 시간에는 ESP8266 (ESP-01) 모듈과 ITEAD STUDIO의 4.3인치 LCD를 이용하여 인터넷으로부터
날씨 정보를 가져와 출력하는 작업을 해보았다. 비록 LCD 연결이 어렵기는 했지만 전체적으로 동작하는 데는
큰 문제가 없었다. 다만 하고자 했던 내용 중에 제대로 진행하지 못한 것이 인터넷을 이용하여 BMP 이미지를
불러온 후 LCD에 출력하는 부분인데 Wi-Fi 센서에서 이미지를 가져오는 방법을 잘 모르겠다…ㅠ.ㅠ


그리고 불만스러운 것이 openweathermap API가 보내주는 날씨 정보가 영 형편이 없다. 어느 순간부터
최고 기온과 최저 기온이 계속 동일하게 받아진다…-.-


아무튼 이번에는 날씨 정보 아래 큰 여백에 시계를 표시할 계획이었으나 별도의 아두이노와 LCD를 이용하여
시계를 따로 구현하기로 했다. 어차피 LCD 크기가 작기 때문에 2개의 LCD를 이용할 계획이었고 지난 번에
밝힌 목표에서 아두이노간의 통신을 통해 정보를 넘기는 작업도 진행을 해야 하기에 그냥 따로 구현하는 쪽이
좋을 것 같다고 판단했다.


시작 하자마자 난관…ㅠ.ㅠ

지난 번 4.3인치와 3.2인치 LCD를 같은 ITEAD STUDIO것으로 구매를 했다. 그리고 Wi-Fi 연결을 통해
날씨 정보를 보여주는 작업에 4.3인치를 사용했다. 같은 회사 제품이 핀 배열도 동일하기 때문에 이번 작업은
누워서 떡먹기라고 지레 짐작을 했건만…이상하게 지난 번과 동일하게 아두이노 메가와 LCD를 직접 연결을
했는데도 불구하고 백라이트의 하얀 불빛만 보이고 예제 코드들이 하나도 동작을 하지 않았다. 우선 확인한
것은 4.3인치와 3.2인치가 사용하는 컨트롤러 칩이 다르다는 것. UTFT 라이브러리는 LCD 초기화 시 컨트
롤러 모델을 지정한 상수를 첫 번째 파라미터로 받기 때문에 이 값을 수정해가면서 열심히 시도를 해보았으나
아무리 해도 도대체가 반응이 없었다. 판매처에 문의를 해보고 가이드 해주는 대로 따라했는데도 역시 증상은
동일하였다. 일단 제품 불량으로 잠정 결론 짓고 더 이전에 구매한 waveshare제의 2.8인치 LCD를 사용
하기로 했다.

2.8" 쉴드 형태다.2.8" 화면 출력3.2" 아무래도 불량...ㅠ.ㅠ


지난 글에서 말했듯이 waveshare의 2.8인치 LCD는 쉴드 형태로 아두이노를 덮어버리면 다른 핀들을
사용하기가 상당히 답답해진다. 그래서 일단 바로 아두이노에 결합하지 않고 점퍼 케이블을 이용하여 연결
하기로 했다. 이 쉴드는 아두이노 우노에 맞춰져 있기에 아두이노도 우노를 사용하기로 했다. 이전의 ITEAD
제품보다 사용하는 핀 수가 적기는 하지만 아두이노 우노를 사용하니 사실상 남는 핀이 거의 없었다. 다행이
사용할 RTC 모듈은 A4(SDA)와 A5(SCL)에 연결하면 되기에 문제될 것이 없었다.


어찌되었건 이렇게 연결하고 나니 지난 번과 다름없이 심란한 모습이 되었다…-.-



RTC 모듈 사용하기

이번에 사용한 RTC 모듈은 PCF8563이라는 모듈로 앞서 말한대로 SDA와 SCL로 통신하고 전원은 3.3V를
사용하는 녀석이다. 사용하는 핀이라고는 4개밖에 없어 달리 연결도는 올리지 않는다. 아두이노 메가라면
같은 이름끼리 (SDA -> SDA, SCL -> SCL, GND -> GND, VCC -> 3.3V)로 연결하면 되고 우노인 경우
SDA -> A4, SCL -> A5로 연결하면 된다. 이 모듈은 배터리가 포함된 모듈이며 아래 이미지의 모듈 하단에
보이는 점퍼를 그림상의 왼쪽에 꽂으면 아두이노의 전원만을, 오른쪽에 꽂으면 전원이 안들어올 시 포함된
배터리를 이용하여 계속 작동하게 된다.


라이브러리는 아래 링크에서 다운로드 받았다.

https://bitbucket.org/orbitalair/arduino_rtc_pcf8563/downloads


사용법을 알기 위해 검색을 해봤더니 이 모듈을 사용한 케이스가 전무하다시피 했다. 나중에 알고보니 이녀석
다른 모듈에 비해 가격이 비쌌다. 난 왜 하필 이 비싼 걸 산걸까…ㅠ.ㅠ 그러고보니 이 모듈도 이번에 사용한
LCD와 같이 waveshare 로고가 찍혀 있다.


아무튼 라이브러리는 잘 작동을 하였고 직관적인 API로 사용하기도 어렵지 않았다. 다만 완성된 시계에 문제가
좀 있는데 이 문제가 모듈 탓인지 다른 문제인지 모르겠다.


그리고 또 난관…ㅠ.ㅠ

사실 지금까지 개발일을 해오면서 시계도 꽤 많이 만들어봤다. 웹용으로도 만들어보고 아이폰용으로도 만들어
보고…하지만 그 때는 시간만 받아와서 변수에 넣고 출력만 하면 되었다. 물론 지금도 그 과정에는 크게 다름이
없다. 다만 지금은 LCD까지도 처리를 해주어야 한다는 것을 간과했다. 예전에 했던 방식으로 그냥 했더니…
아래 사진과 같이 앞서 출력된 내용 위에 다음에 출력된 내용이 겹쳐지면서 알아볼 수 없는 형체가 표시되었다.


그랬다…일단 데이터를 출력한 후 같은 자리에 다음 데이터를 출력하기 위해서는 앞서 출력된 내용을 지운 후
출력을 해줘야 했던 것이다. 기존의 개발은 화면에서 어떻게 처리해줄 것인가는 전혀 신경을 안써도 되었지만
아두이노는 그렇지 않았던 것이다.
(아무래도 이 부분은 추가 확인이 필요할 것 같다. 지난 번 날씨 표시 구현 시에는

별다른 추가 작업 없이 그냥 화면에 출력만 해주어도 문제가 없었는데...아마도 라이브러리 차이가 아닐런지...)


방법은 알았으나 이 방법을 어떻게 구현해야 할지가 또 난관이었다. 일단 기본적으로 이 LCD 라이브러리에는
lcd_clear_screen라는 화면을 특정 색깔로 채우는 함수가 있다. 일단 이 함수를 사용해보기로 하였으나
문제가 있었는데…1초마다 화면 전체가 껌뻑거리는 것이었다. 아무리 대충만드는 시계이지만 이건 아니다 싶다.


결국 이 함수와 동일한 기능을 하지만 특정 범위만 처리하는 lcd_clear_partscreen라는 함수를 별도로
만들었고 다행히 잘 작동하였다. 아무래도 waveshare와 나는 궁합이 별로 안맞는 것 같다…-.-


lcd_clear_partscreen 소스 코드

void lcd_clear_partscreen(uint16_t hwColor, uint32_t l, uint32_t t, uint32_t w, uint32_t h)  
	{
		uint32_t i, wCount = w;
		wCount *= h;
		
		lcd_set_cursor(l, t);
		lcd_write_byte(0x22, LCD_CMD);
		
		__LCD_DC_SET();
		__LCD_CS_CLR();
		for (i = 0; i < wCount; i ++) {
			__LCD_WRITE_BYTE(hwColor >> 8);
			__LCD_WRITE_BYTE(hwColor & 0xFF);
		}
		__LCD_CS_SET();
	}


사실 전체적인 소스가 뭔 내용인지는 잘 모르겠지만 직관적으로(좋은 말로 직관이고 그냥 대충 찍어서…) LCD
의 가로 해상도가 들어가는 wCount와 전체 해상도에 해당하는 wCount \*= h에 각각 필요한 폭과 넓이를
파라미터로 전달 받고 최초 위치를 지정하는 lcd_set_cursor(l, t);에도 역시 값을 파라미터로 전달 받도록
수정하여 각 영역(시간, 분, 초, 년도, 월, 일)이 갱신될 때 그 영역만 지웠다가 다시 출력하도록 구현하였다.


그래서 일단 아래 동영상과 같이 디지털 시계가 하나 완성되었다.


끝나지 않은 난관

그런데 위의 동영상을 보면 알겠지만 간혹가다가 2초가 튀어버린다. 처음에는 1초 체크를 delay(1000)으로
했었는데 이 때는 거의 10초에 한 번은 2초를 건너 뛰었다. 즉, 1, 2, 3, 4, 6, 7, 8, 9, 0 이런 식으로… 그래서
이번에는 millis() 함수를 이용하여 1초를 측정하여 처리했는데 이렇게 하니 좀 나아지긴 했지만 그래도 1분에
한 번꼴로 2초를 건너 뛴다. 모듈의 문제인지 로직의 문제인지 아직 해결을 못하고 있다.


그리고 시간과 날짜의 출력 라인 제일 앞에 불필요한 점이 찍히는 문제도 해결이 필요하다.


다음 진행 계획

지난 글에서 언급 했듯이 이제 날씨 표시와 시간 표시를 각각의 아두이노와 LCD를 이용하여 만들었으니 다음에는
지난 시간에 만든 Wi-Fi를 통해 날씨를 가져오는 아두이노 쪽에서 시계를 표시하는 아두이노쪽으로 정보를 보내서
날씨와 시간이 한 화면에 출력되도록 구현을 해봐야겠다.


또 어떤 난관이 기다리고 있을지 자못 기대되는 바이다…-.-


아두이노 디지털 시계 최종 소스

https://github.com/mazdah/ArduinoSamples/tree/master/smart_mirror_code3

블로그 이미지

마즈다

이제 반백이 되었지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


진짜를 만들어보자 - 3. LCD 연결 및 Wi-Fi를 통한 날씨 정보 가져오기


우선 지난 포스팅에 언급한 waveshare사의 LCD 라이브러리에서 똑바로 선 형태의 폰트를 출력할 수
있도록 수정한 함수를 올린다.


//display a char at the specified position on lcd.
void TFT::lcd_display_char2(uint16_t hwXpos, //specify x position.
 uint16_t hwYpos, //specify y position.
 uint8_t chChr,   //a char is display.
 uint8_t chSize,  //specify the size of the char
 uint16_t hwColor) //specify the color of the char
{      	
	uint8_t i, j, chTemp;
	uint16_t hwXpos0 = hwXpos, hwColorVal = 0;

	if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
		return;
	}

	int width = 8;  // 폰트의 가로 폭
	if (SEGMENT18_XXL == chSize) { 
		width = 16;
	} else if (DOTMATRIX_M_SLASH == chSize) {
		width = 8;
	}

	hwColorVal = hwColor;
   
	for (i = 0; i < chSize; i ++) {     	
		if (SEGMENT18_XXL == chSize) { 
			chTemp = pgm_read_byte(&segment18_XXL[chChr - 0x20][i]);

			if (i != 0 && (i % 4) == 0) {
				hwYpos ++;
			}
		} else if (DOTMATRIX_M_SLASH == chSize) { 
			chTemp = pgm_read_byte(&DotMatrix_M_Slash[chChr - 0x20][i]);

			if (i != 0 && (i % 2) == 0) {
				hwYpos ++;
			}
		}

		for (j = 0; j < width; j ++) {
			if (chTemp & 0x80) {
				lcd_draw_point(hwXpos, hwYpos, hwColorVal);
			}
			chTemp <<= 1;
			hwXpos ++;

			if (hwXpos > hwXpos0 + (width * 2 - 1)) {
				hwXpos = hwXpos0;
			}
		}  	 
	} 
}


특별히 수정할 내용은 없으나 폰트의 크기에 따라 width를 조정해야 한다.


LCD와 Wi-Fi 센서 연결


일단 지난 번 waveshare LCD에 UTFT 폰트를 쓸수 있도록 손을 써뒀지만 두 가지 문제가 있었다.
첫 번째는 화면 크기가 작다는 것. 2.8인치의 크기인데 내가 가진 하프 미러의 가장 작은 사이즈가
A4지 절반 크기라서 2.8인치로는 폰트 크기를 크게할 경우 보여줄 수 있는 정보가 얼마 없었다.
다음은 정말 중요한 이유로 이 LCD가 쉴드 형태로 LCD를 장착할 경우 아두이노에서 사용 가능한
포트가 남지 않는다는 것이다. 뭐 아두이노 메가를 사용하면 되겠지만 이 제품은 호환 기종에 메가가
빠져있어서 메가에서는 장착해서 바로 사용을 못한다. 아마도 라이브러리에서 설정을 조금 변경하면
될 것 같지만 이게 아니더라도 할일이 태산인데…-.-


그래서 화면 크기도 좀 키우고 할 겸 이번엔 ITEAD STUDIO라는 곳에서 나온 4.3인치와 3.2인치
LCD를 구매했다. UTFT 라이브러리를 사용하는 놈이라 폰트 사용도 쉬운 장점이 있었다.




그런데 이놈도 제대로 사용을 하기 위해서는 별도의 쉴드를 사용해야 했다. 더군다나 이놈이 사용하는
쉴드는 아두이노 메가에서도 여분의 포트를 남기지 않고 모두 덮어버린다…ㅠ.ㅠ (포장은 모두 깔끔해서
좋다~)




이렇게 되면 큰 문제가 생긴다. 라즈베리파이의 경우 Wi-Fi, 이더넷, USB 등등 그 자체로 하나의 PC
와 같기 때문에 별도로 연결시켜줄 것이 없으나 아두이노는 본체가 달랑 컨트롤러 하나이기에 Wi-Fi
모듈도 붙여줘야 하고, 시계를 표현하기 위해 시계 모듈도 따로 붙여줘야 하고 그밖에 기능을 추가
하고자 할 때마다 센서 모듈을 별도로 연결해야 하기에 포트가 모자라면 심각한 제약이 발생하는 것이다.


그렇기 때문에 일단 쉴드를 사용하지 않고 LCD를 직접 아두이노 메가에 연결할 수 있는 방법을 찾아야 했다.
데이터 시트를 자세히 보면 아마도 방법이 있겠지만 문돌이 지식이야 뻔한 것이고 게다가 데이터 시트가 

모두 영어로 되어있는지라 일단은 구글에서 검색을 해야 했다. 그리고 다행히 아래 링크된 사이트를 찾아

무사히 연결을 할 수있었다. 물론 연결을 하고 난 뒤의 모양새는 조금 심란하다…ㅠ.ㅠ


LCD 연결 참고 사이트 : https://forum.arduino.cc/index.php?topic=101029.0




일단 위 이미지에서 보듯이 총 40개의 핀이 있고 이 중에 사용하지 않는 핀을 7개정도 빼면 33개 그리고
SD카드나 터치스크린 기능을 사용하지 않을 것이면 여기서 또 10개정도는 더 포트를 절약할 수 있다.
나는 SD카드를 제외한 나머지 핀들을 모두 연결하였다.


그리고 다행히도 정상적으로 작동을 하였다.


다음은 출력에 필요한 정보를 가져오기 위해 Wi-Fi 센서를 연결하였다. 이 부분은 워낙 자료가 많으니
생략을 한다. LCD와 Wi-Fi 모두 아두이노로부터 전기를 공급받아야 하기에 3.3V포트와 GND 포트는
빵판을 이용하여 공유하였다(LCD와 Wi-Fi 모두 3.3V를 필요로 한다).


Wi-Fi 모듈 역시 정상 작동 확인 완료!!!


openweathermap API 호출


하드웨어 준비는 마무리 되었으니 이제 인터넷에서 정보를 가져와서 LCD에 출력해주면 된다.
말은 참 쉽다…-.- 일단 Wi-Fi 센서의 경우 일전에 인터넷을 통해 LED 점등 테스트를 하다가 실패한
적이 있다. 아마도 스케치 코드라든가 센서 연결등의 문제라기보다는 공유기를 통해 Wi-Fi 센서로
연결하는데 문제가 있었던 듯하다. 하지만 이번에는 공유기를 통해 외부 웹사이트를 호출하는 것이므로
아마도 쉽게 될 것이라고 생각했다.


우선은 AT 명령어를 이용하여 외부 인터넷에 접속하고 응답을 확인하는 것은 무난히 성공을 하였다.
하지만 AT 명령어를 직접 사용하는 것보다는 뭔가 쉽게 접근 가능한 라이브러리가 있을 것으로 생각
되었다. 그런데 검색을 해봐도 대부분이 Wi-Fi 쉴드 사용을 기준으로 SoftwareSerial을 이용하는
라이브러리밖에 없었다. 나는 아두이노 메가를 사용 중이었고 Wi-Fi 센서는 Serial3에 연결을 해서
이 상태로 사용할 수 있는 라이브러리가 필요했다. 검색 끝에 드디어 아래의 라이브러리를 찾았다.


ESP8266 라이브러리 : https://github.com/itead/ITEADLIB_Arduino_WeeESP8266


사용법도 그리 어렵지 않아 쉽게 코드를 짜고 인터넷 접속 확인을 할 수 있었다.


다음은 어디서 어떤 정보를 가져올 것인가를 선택해야 했다. 우선은 가장 만만한 날씨 정보를 가져오기로
했다. 처음에는 기상청의 오픈 API를 이용하려고 생각했으나 가입이 필요하고 가입하는 과정에서 내가
사용하는 MAC에서는 뭔가 제대로 진행되지 않는 부분이 있었다. 도대체 언제까지 윈도우와 IE에 발목을
잡혀있어야 하는 것인지…-.-


그래서 가입과 사용에 별다른 제약이 없는 openweathermap이라는 서비스를 이용하기로 하였다.
아직은 제작 진행 중이니 이정도면 테스트하기에는 충분하다고 판단되었다. 가입하고 APP ID를 받아
API 호출을 테스트 해보았다. 아래와 같이 날씨 정보를 잘 받아왔다^^


{{“coord":{"lon":126.98,"lat":37.57},"weather":[{"id":721,"main":"Haze","description":"haze","icon":"50d"},{"id":701,"main":"Mist","description":"mist","icon":"50d"}],"base":"stations","main":{"temp":2.43,"pressure":1012,"humidity":74,"temp_min":1,"temp_max":3},"visibility":10000,"wind":{"speed":2.1,"deg":250},"clouds":{"all":90},"dt":1486282800,"sys":{"type":1,"id":8519,"message":0.0111,"country":"KR","sunrise":1486247522,"sunset":1486285237},"id":1835848,"name":"Seoul","cod":200}


다음은 이렇게 JSON으로 받아온 정보를 보기 좋게 LCD에 출력을 하는 일이 남았다.
JAVA라면 순식간에 해치울텐데…이거 스케치에서는 어떻게 해야 하나…ㅠ.ㅠ
하지만 역시 세상에는 많은 천사들이 있다. 열심히 구글을 검색한 결과 역시 아래와 같은 라이브러리를
찾아냈고 아주 쉽게 처리할 수 있었다.


ArduinoJson 라이브러리 : https://github.com/bblanchon/ArduinoJson


그리고 비록 아직은 뭔가 모자라지만 아래와 같이 정보를 출력할 수 있게 되었다.



첩첩 산중…


사실 처음 아두이노로 스마트 미러를 만들어보고자 생각했을 때는 라즈베리파이로 만든 스마트 미러 정도는
만들어보려고 시작을 했다. 심지어는 음성 인식까지…하지만 아두이노가 얼마나 low level의 하드웨어인지
제대로 인식을 못하고 있었던 듯하다. 하드웨어 연결, 인터넷 연결, 입력과 출력…하나 하나가 모두 엄청나게
손이 많이 가는 작업들이었다. 개발자 입장에서 말하자면 java로 짤 코드를 어셈블리로 짜고 있는 느낌이랄까
…-.- 게다가 아직은 폰트를 영문폰트밖에 구하지 못해서 한글 표현이 또 걱정이다.


그래도 우여곡절 끝에 인터넷에서 날씨 정보를 가져와서 LCD에 출력하는 기능까지 구현을 했다. 아직도 
갈 길이 멀지만 일단 칼을 뽑았으니 무라도 잘라보련다.



전체적인 계획은 아두이노 메가 2대를 이용하여 한 대에는 날씨와 날짜 및 시간 정보를 보여주고 다른
한 대를 통해서는 뉴스라든지 현재 내가 개발중이 ToDo 서비스로부터 할 일 정보를 가져와서 보여줄
예정이다. 물론 각각의 아두이노에서 별도로 Wi-Fi를 통해 정보를 가져오는 것은 뭔가 비효율적이라
생각되어 첫 번째 아두이노에서 모든 정보를 가져오고 아두이노간의 시리얼 통신을 통해 다른 한 대로
정보를 넘겨 처리할 생각이다. 과연 얼마나 잘 진행될 수 있을지 자못 궁금하다…-.-


다음 시간에는 시계 모듈을 이용하여 오늘 보여준 날씨 정보 하단에 날짜와 시간을 출력해보고자 한다.
또 얼마나 시간이 걸릴지… 진행되는 내용의 소스코드는 아래 링크에 공유한다. 나는 나쁜 개발자라
주석같은 거 없당~^^


소스코드 : https://github.com/mazdah/ArduinoSamples

블로그 이미지

마즈다

이제 반백이 되었지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


진짜를 만들어보자 - 2. LCD 폰트 살펴보기


지난 글에서 밝혔듯이 아두이노를 이용하여 TFT LCD에 문자열을 출력하는 방식은 꽤나 
생소했다. 그냥 일반적인 웹 시스템이나 모바일 애플리케이션을 개발할 때는 그냥 폰트 파일
하나 가져다 놓고(물론 폰트 파일의 구조가 어떻게 생겼는지는 알 필요도 없다. 그냥 폰트
이름만 알면 되지) 이름과 size만 지정해서 사용하면 그만이었는데…


아무튼 새로운 지식의 장벽 앞에 조금 막막했다.


닥글링? (닥치고 구글링?)


우선 ‘아두이노’, ‘LCD’, ‘폰트’, ‘TFT LCD’ 등등의 검색어로 구글링을 해보았다. 물론 네이버
검색도…역시나 검색의 바다에는 쓸만한 정보들이 차고 넘친다. 먼저 내가 참조한 사이트들의
링크를 공유한다.


사실 대부분의 내용들이 자세히 살펴보지 않으면 상세한 부분까지 알기 힘든 수준이었다.
특히나 나같은 문돌이들은 일단 수학적인 개념이 들어가면 멘붕 상태에서 이리저리 헤매기
일쑤고…-.- 그래도 그나마 그림으로 표현한 내용들은 어느 정도 이해를 할 수 있었다.


폰트의 구조 - 장인의 한 땀…


일단 위에 링크된 곳들을 돌아다니면서 LCD 화면에 폰트가 어떤식으로 표시되는지는 대략
알 수가 있었다.


LCD상의 하나의 점(pixel)을 하나의 bit로 표시하고 그 점들의 그룹을 한 문자의 영역(이
영역이 바로 폰트의 사이즈라고 보면 되겠다. 8 X 12, 8 X 16, 16 X 22 등)으로 삼고
그 영역 내에서 문자의 형태를 bit값 1로 채워나가는 것이다. (첫 번째 링크의 3. Bitmap
font(비트맵 폰트)의 구조 참조)


그래서 일단 waveshare에서 제공하는 라이브러리에 포함된 font.c 파일에 있는 배열 중
하나에서 ‘A’라고 주석된 배열을 한 번 풀어보기로 했다. 배열의 요소들은 16진수로 표현
되어있으니 이걸 다시 2진수로 만들어보았다.


원본 배열 : 0x00,0x40,0x07,0xC0,0x39,0x00,0x0F,0x00,0x01,0xC0,0x00,0x40
2진수로 변환한 배열 : 00000000,01000000,00000111,11000000,00111001,00000000,
00001111,00000000,00000001,11000000,00000000,01000000


그리고 이렇게 2진수로 변환한 배열을 2개(2byte)씩 잘라 세로로 배치를 해보았다.
그랬더니 아래와 같은 모양이 되었다(블로그에 사용된 폰트가 가변폭이라서 이미지로 첨부
하였다).




오호~!!! 뭔가 보이는가? 조금 더 알아보기 쉽게 0울 모두 지워보자





마치 그냥 암호처럼 보이던 배열이 이렇게 풀어놓고 보니 어렴풋이 문자의 형상이 나타난다. 
이렇게 풀어놓은 것 중에 1로 표시된 것들이 LCD상에서 빛을 내며 문자로 출력되는 것이다. 
비트맵 폰트라는 것이 이렇게 모눈종이같은 영역에 한땀한땀 정성들여 만들어진다는 것을 
처음 알았다…ㅠ.ㅠ


끝이 아니네?


아하~! 일단 폰트의 구조를 알았으니 응용하면 되겠구나.
하지만 나에게는 장인정신이 없으니 한땀한땀 폰트를 만들 수는 없는 일!
대충 비슷한 폰트 크기 큰걸루다가 구해서 쓰면 내가 산 LCD에도 큰 폰트를 출력할 수 있겠네~


그리고 다시 폰트를 찾기 위해 구글링…그러다가 아래의 사이트를 찾았다. 


굉장히 친절한 사이트였다. LCD 모듈도 파는 것 같고 다양한 LCD 라이브러리도 있고 중요한 
것은 이미지 파일로 폰트 파일을 만들어주기도 하고 아예 그렇게 만들어진 폰트를 다운로드 할
수도 있다. 그것도 모양과 크기도 다양하게!


오호 횡재다~ 하고 다양한 폰트를 다운로드 받었으나…웬걸…내가 가진 폰트는 2차원 배열로
구성되어있는데 다운로드 받은 폰트파일은 1차원 배열이네? 게다가 처음 한 줄은 뭔가 byte
수도 모자라고…




다행히 라인별로 아스키 문자가 주석으로 붙어 있어서 각 라인을 하나의 배열로 만들어 2차원
배열로 만들면 되겠다는 것을 쉽게 알 수 있었다. 나중에 알았지만 처음 4바이트는 폰트의
크기와 종류를 나타내는 값이었다. 그래서 일단 폰트 파일을 다음과 같이 수정했다.




자~ 이제 준비는 끝났고 출력만 해보면 되겠다~물론 라이브러리에서 상수 지정하고 새로
지정한 상수 선택시 추가한 폰트를 표시하도록 몇가지 수정을 거쳤다. 그리고 기운차게
스케치의 업로드 버튼을 클릭!!!


악!!! 이거 왜이래!!!




폰트가 나오기는 나왔는데 이게 영 상태가 병맛이다. 옆으로 누워있는데다가 가운데는 홍해가
갈라지듯 갈라져있고 게다가 이게 시계방향으로 돌려도 문자의 좌우가 뒤집힌 것이 분명한…
이게 아예 글자도 아닌 것 같이 찍혔으면 아예 뭔가 크게 잘못되었구나 하고 처음부터 차근차근
다시 해볼텐데…뭔가 글자인 것 분명한데 돌아가고 뒤집히고 한 모양이다보니 괜히 이리저리
머리를 쓰게 만든다…ㅠ.ㅠ for문을 고쳐볼까? 배열에서 요소들의 순서를 바꿔볼까?
아는가? 뭔가 조금만 손대면 될 것 같은데 어디를 손대야 할 지 모를 때 엄습하는 그 답답함…ㅠ.ㅠ


상투적인 것이 가장 확실하다!


사실 이 문제 해결을 위해 하루를 꼬박 보냈다. for문도 수차례 고쳐보았고, 배열 요소의 순서도
여러번 바꿔보았다. 하지만 도무지 답이 나오지 않았다. 결국 처음 폰트에 대해 이해할 때 했듯
배열을 분해해보기로 했다. 짜잔~ 분해했더니 아래 그림과 같이 거대한 문자가 하나 나왔다.
이거 나름 상당한 노가다다…-.- (로봇을 만들 때도 그렇고 이 것도 그렇고…분명 뭔가 지식 산업
에 대한 과제를 하는 듯한데 왜이리 육체노동을 하는 느낌이지…ㅠ.ㅠ???)




일단 풀어는 놨는데…뭔가 이상하다. 물론 크기가 엄청 큰 것도 있지만 그 것 말고도 뭔가
이상하다…waveshare에 포함된 폰트는 풀어헤쳐놓으니 대가리를 왼쪽으로 향하고 누운
모양이었는데 이 UTFT 폰트는 정상적인 형태로 똑바로 서있는 것이다!


라이브러리에 포함된 출력 함수가 옆으로 누운 폰트를 화면상에 똑바로 보이도록 처리해주는
함수였으니 똑바로 선 폰트가 이상하게 출력되는 것은 당연한 일인 것이다. 함수를 좀
분석해보려 하니 짧은 함수이지만 shift 연산도 있고 또 16진수 bit 연산도 있고…간만에
보니 뒷골 땡기는 연산들이 좀 있어서 일단 그림으로 이해해보기로 하였다.



                



그림을 보니 A와 D를 축으로 회전한 모양이다. 그러고보니 UTFT 폰트가 이상하게 나왔던
모양과도 딱 들어맞는다. 결국 함수를 고치는 수밖에는 답이 없어보였다. 그나마 다행인 것은
사용하려는 폰트가 똑바로 선 형태의 폰트이다보니 좌표때문에 머리아플 일은 없다는 것이다.
그냥 순서대로 x좌표를 이동하면서 출력하다가 폰트 사이즈에 따라 적절한 시점에 y좌표를
증가시켜주기만 하면 된다.


그리고 드디어~!




waveshare 라이브러리에서 UTFT의 다양한 폰트를 사용할 수 있게 된 것이다…ㅠ.ㅠ
(그럼에도 불구하고 마지막 Cyan 색상의 가장 큰 폰트는 뭔가 폰트 이미지하고 모양이
맞지 않는다…-.-)


아직도 남아있는 숙제들


다행히 사용하고자 하는 폰트가 똑바로 선 형태라 쉽게 함수를 만들어 사용할 수 있게
되었다. 하지만 아직 숙제가 있다. 바로 화면 회전에 따라 가로모드 세로모드에서 모두
자유자재로 정상적인 형태의 폰트를 보여주는 것! 그리고 가장 중요한 한글의 처리!!!


이와 관련된 자료도 위에 링크한 사이트에 많은 설명이 있지만 좌표 예기만 들어도
머리가 지끈거린다…ㅠ.ㅠ 일단 머리아픈 일은 여기까지 마무리 하고 새로 주문한
LCD들이 UTFT 라이브러리를 지원한다고 하니 조금은 편하게 작업을 좀 해보자…ㅠ.ㅠ


다음 과제는 Wi-Fi 센서를 통해 웹 서버로부터 날씨나 시간 데이터를 가져와서 예쁘게
뿌려주는 것이다!


수정한 라이브러리를 공유드리고 싶은데 라이센스 정보를 확인 못해서 일단 확인 후
별다른 제약이 없으면 UTFT 폰트를 사용할 수 있도록 수정한 라이브러리를 공유하도록
하겠습니다.

블로그 이미지

마즈다

이제 반백이 되었지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


진짜를 만들어보자 - 1. LCD에 문자 출력하기


지난 번 “2시간만에 스마트 미러 만들기”를 보시고 실소를 금치 못한 분들이 많이 계실 것이다.
그렇다! 그것은 완벽한 개사기…라기보다는 ‘훼이크’라고 애교스럽게 표현하기로 하겠다…^^;;;


그러면 그렇게 훼이크로 점철된 인생을 살 것이냐? (조금 비약이 심한가…-.-)


그럴 수는 없다. 그래서 이제 진짜를 만들어보려고 한다.
오늘부터는 진짜 스마트 미러 만들기가 시작된다!


아두이노의 제약


우선 시작을 하면서 왜 스마트 미러를 만들 때 라즈베리파이를 이용하는지 제대로 깨달았다.
한마디로 말해서 자바로 프로그램을 짤 것이냐 조금 과장해서 어셈블리로 프로그램을 짤 것이냐의
차이 정도 될 것 같다.


라즈베리파이는 그 자체로 한 대의 컴퓨터다. 즉, PC에 설치할 수 있는 운영체제가 거의 온전한
모습으로 라즈베리파이에 설치 될 수 있는 것이다. 그 말은 화면(LCD)에 문자를 표현하는데 아무런
제약이 없다는 것이다. 물론 이미지도 마찬가지…게다가 다양한 폰트를 자유자재로 이용할 수 있다.
음성이나 모션 인식 등 특별한 기능의 구현이 아니라면 단지 화면에 데이터를 출력해주는 것은
일도 아니라는 것이다.


그런데 아두이노는…ㅠ.ㅠ
그야말로 알파벳 ‘A’ 하나 출력하는데도 이탈리아 장인 정신을 가득 담아 한땀한땀 보여주어야 한다.
물론 모든 LCD 제품들이 라이브러리를 제공해주기 때문에 함수 하나 호출하면 가볍게 출력해
주기는 하지만 폰트 종류, 화면 방향 등 고려해야 할 사항이 다르고 폰트조차도 구성 방식이 달라
라이브러리 별로 사용 가능한 폰트가 따로 있다(물론 얼마든지 수정하여 사용 가능하고 이번 글의
주요 내용이 바로 그것이다).


얼마전 아이들 풍선 껌 종이에 적힌 내용을 보니 이런 글이 적혀있었다.


“집을 나서자 마자 집에 돌아가고 싶어졌다”


그렇다…스마트 미러 만들기를 시작하자 마자 아무 것도 하고싶지 않아졌다…ㅠ.ㅠ


준비물


일단 화면에 정보를 뿌려주는 것이 1차 목표이기에 별다른 준비물은 없다. 아두이노 우노(호환)와
2.8” 크기의 LCD 하나가 전부이다.




헝그리 스마트 미러 제작이 목표이기에 LCD는 크기 대비 가장 싼 녀석으로 골랐다. 메X솔X션에서
2.8”를 23,100원에 그리고 혹시나 해서 2.2”를 11,000에 구매했다. 2.8” 제품은 waveshare라는
브랜드의 제품이었다.


waveshare 제품 페이지 : http://www.waveshare.com/wiki/2.8inch_TFT_Touch_Shield

waveshare 2.8" TFT LCD shield



그리고 아시는 분은 아시겠지만 컵라면이 하나 따라왔다. 스마트미러 만드는 데 쓰라고 보내주신 
것은 아니겠기에 맛있게 먹어줬다(이자리를 빌어 사장님께 감사드립니다^^;).


그런데 준비물을 준비하는데서부터 난감한 미래가 예견되었다. 2.8” LCD는 쉴드 타입인데 이걸
아두이노 우노에 장착하고 나면 남는 핀이 없다…


이런게 찰떡 궁합?



나중에 Wi-Fi 센서도 연결하고 모션 센서나 기타 등등의 센서들을 연결을 해야 할텐데…급한대로
메가에다 장착을 했더니 장착은 잘 되는데 작동을 안한다. 아마도 핀 배열이 안맞는 것이 있나보다. 
일단 이 문제는 나중에 해결하고 우선은 LCD를 통해 문자를 출력하는 것 부터 시작하기로 했다.


참고로 2.8” 크기도 작은 것 같고 이 제품의 라이브러리도 좀 빈약한 것 같아서 아XX팩X리에서
추가로 4.3”와 3.2” 제품을 각각 하나씩 더 구매했다. 헝그리가 목표인데…-.-


또 하나의 장벽


일단 메X솔X션의 제품 페이지에 있는 링크를 찾아가 라이브러리를 다운로드 받고 스케치를 실행해
보았다. 라이브러리를 스케치에 추가하고 샘플 코드를 열어보았다. 그리고 실행!
오~잘된다 잘돼!!!


기본 예제 출력



스마트 미러를 위해 배경색은 검게 문자는 흰색으로도 한 번 출력해보고


색상만 변경~



역시 잘된다!


이제 글자 크기를 좀 키워보자!
어…그런데…폰트가…
일단 출력 함수에 파라미터로 폰트 사이즈를 넘기도록 되어있는데 이 폰트 사이즈가 단 2개만
상수로 정해져 있었다. 그러니까 기본적으로는 2종류 크기의 폰트밖에 사용할 수 없게 되어
있었던 것이다…-.- 아무리봐도 스마트 미러에 사용하기에는 폰트가 너무 작은데…


그런데다가 늘 워드 프로그램에서 간단하게 폰트를 선택해서 쓰기만 하다보니 도대체 이 LCD
에서는 폰트를 어떻게 사용하는지 감이 안잡히는 것이다.


아무래도 라이브러리를 까보는 것 밖에는 답이 없을 것 같았다. 그리고 다행히 라이브러리 소스
안에서 font.c라는 파일을 하나 찾았다. 올타꾸나!하고 파일을 열었는데???
이건 뭔가요??? 1byte Hex값이 잔뜩 적힌 2차원 배열 2개가 다소곳하게 코딩되어 있는데…
얜 어떻게 쓰는건가…


암혼가...ㅠ.ㅠ???



17년 개발자 짬밥으로 1바이트 아스키 문자 95개에 대해 각각 12바이트로 표현을 하고 있는
것 같기는 한데…이게 어떻게 화면에 표시가 되는 것인지 도통…ㅠ.ㅠ


어쩔 수 없이 다시 구글링을 시작…
그리고…신세계를 보게 되었다!


글이 길어져 다음 포스팅에 계속합니다. 다음 포스팅에는 LCD에서 폰트 구조와 사용법에 대해
간단하게 알아보겠습니다.

블로그 이미지

마즈다

이제 반백이 되었지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^