반응형

라즈베리 파이 카메라를 사용해 보자.


중국에서 구매한 라즈베리 파이용 카메라가 1주일만에 배송 되었다. 라즈베리 파이에서 판매하는 정품 카메라가 아닌 5MP 저가 호환 카메라이다. 약 3만원에 판매되는 8MP 정품 카메라보다 성능은 떨어지지만 가격이 1/10이다.


뒷면


HDMI Port와 Audio Jack 사이에 CSI Camera Port가 있다.


보호 테이프를 제거하고 latch를 들어 올린 다음 케이블을 삽입하고 고정한다.



라즈베리 파이를 부팅하고 Raspberry Pi Configuration에서 Camera - Enable을 선택한다. 재부팅 한다.


파이썬 Picamera 모듈을 사용해 보자. (Picamera 모듈은 기본 설치되어 있다)


파이썬 코드를 실행하면 라즈베리 파이에 연결한 카메라 LED에 불이 들어오고 preview 화면이 30초동안 표시된다.


반응형
Posted by J-sean
:
반응형

2.2인치 ILI9341 TFT LCD를 아두이노와 함께 사용해 보자.


알리에서 약 5천원에 구매한 ILI9341.


Logic Signal Voltage Level은 3.3V이지만 J1을 납땜해 연결하면 5V의 Signal도 입력 받을 수 있다(납땝이 좀 지저분하게 됐다). 하지만 이 방법 보다는 Logic Level Converter를 사용하는게 좋다.


원래 J1은 이렇게 떨어져 있다.


사실 ILI9341은 아두이노가 아니라 라즈베리파이와 함께 사용해보려 했지만 인터넷에 있는 대부분의 자료들이 더 이상 적용되지 않았다. 백라이트조차 켜지지 않았다. 라즈베리파이 운영체제의 업데이트, 소프트웨어의 업데이트 등으로 변경된 내용이 많아 좀 더 정리가 필요했다.



아두이노와 연결 하자.


ILI9341 - Arduino

DC - 9

CS - 10

RESET - 8

MOSI - 11

MISO - 12

SCK - 13

LED - 3.3V

VCC - 5V

GND - GND


아두이노IDE에서 File - Examples - Adafruit ILI9341 - graphictest을 선택하면 아래 소스가 로드된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/***************************************************
  This is our GFX example for the Adafruit ILI9341 Breakout and Shield
  ----> http://www.adafruit.com/products/1651
  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/
 
 
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
 
// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10
 
// Adafruit shield가 아닌 경우 아래와 같이 핀 추가.
#define TFT_RST 8
#define TFT_MOSI 11
#define TFT_MISO 12
#define TFT_CLK 13
 
// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
 
void setup() {
  Serial.begin(9600);
  Serial.println("ILI9341 Test!"); 
 
  tft.begin();
 
  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 
  
  Serial.println(F("Benchmark                Time (microseconds)"));
  delay(10);
  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(500);
 
  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(3000);
 
  Serial.print(F("Lines                    "));
  Serial.println(testLines(ILI9341_CYAN));
  delay(500);
 
  Serial.print(F("Horiz/Vert Lines         "));
  Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
  delay(500);
 
  Serial.print(F("Rectangles (outline)     "));
  Serial.println(testRects(ILI9341_GREEN));
  delay(500);
 
  Serial.print(F("Rectangles (filled)      "));
  Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
  delay(500);
 
  Serial.print(F("Circles (filled)         "));
  Serial.println(testFilledCircles(10, ILI9341_MAGENTA));
 
  Serial.print(F("Circles (outline)        "));
  Serial.println(testCircles(10, ILI9341_WHITE));
  delay(500);
 
  Serial.print(F("Triangles (outline)      "));
  Serial.println(testTriangles());
  delay(500);
 
  Serial.print(F("Triangles (filled)       "));
  Serial.println(testFilledTriangles());
  delay(500);
 
  Serial.print(F("Rounded rects (outline)  "));
  Serial.println(testRoundRects());
  delay(500);
 
  Serial.print(F("Rounded rects (filled)   "));
  Serial.println(testFilledRoundRects());
  delay(500);
 
  Serial.println(F("Done!"));
 
}
 
 
void loop(void) {
  for(uint8_t rotation=0; rotation<4; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(1000);
  }
}
 
unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  tft.fillScreen(ILI9341_RED);
  yield();
  tft.fillScreen(ILI9341_GREEN);
  yield();
  tft.fillScreen(ILI9341_BLUE);
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  return micros() - start;
}
 
unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(00);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}
 
unsigned long testLines(uint16_t color) {
  unsigned long start, t;
  int           x1, y1, x2, y2,
                w = tft.width(),
                h = tft.height();
 
  tft.fillScreen(ILI9341_BLACK);
  yield();
  
  x1 = y1 = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t     = micros() - start; // fillScreen doesn't count against timing
 
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
 
  x1    = w - 1;
  y1    = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;
 
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
 
  x1    = 0;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;
 
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
 
  x1    = w - 1;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
 
  yield();
  return micros() - start;
}
 
unsigned long testFastLines(uint16_t color1, uint16_t color2) {
  unsigned long start;
  int           x, y, w = tft.width(), h = tft.height();
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
  for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
 
  return micros() - start;
}
 
unsigned long testRects(uint16_t color) {
  unsigned long start;
  int           n, i, i2,
                cx = tft.width()  / 2,
                cy = tft.height() / 2;
 
  tft.fillScreen(ILI9341_BLACK);
  n     = min(tft.width(), tft.height());
  start = micros();
  for(i=2; i<n; i+=6) {
    i2 = i / 2;
    tft.drawRect(cx-i2, cy-i2, i, i, color);
  }
 
  return micros() - start;
}
 
unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
  unsigned long start, t = 0;
  int           n, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  n = min(tft.width(), tft.height());
  for(i=n; i>0; i-=6) {
    i2    = i / 2;
    start = micros();
    tft.fillRect(cx-i2, cy-i2, i, i, color1);
    t    += micros() - start;
    // Outlines are not included in timing results
    tft.drawRect(cx-i2, cy-i2, i, i, color2);
    yield();
  }
 
  return t;
}
 
unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(x=radius; x<w; x+=r2) {
    for(y=radius; y<h; y+=r2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
 
  return micros() - start;
}
 
unsigned long testCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int           x, y, r2 = radius * 2,
                w = tft.width()  + radius,
                h = tft.height() + radius;
 
  // Screen is not cleared for this one -- this is
  // intentional and does not affect the reported time.
  start = micros();
  for(x=0; x<w; x+=r2) {
    for(y=0; y<h; y+=r2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
 
  return micros() - start;
}
 
unsigned long testTriangles() {
  unsigned long start;
  int           n, i, cx = tft.width()  / 2 - 1,
                      cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  n     = min(cx, cy);
  start = micros();
  for(i=0; i<n; i+=5) {
    tft.drawTriangle(
      cx    , cy - i, // peak
      cx - i, cy + i, // bottom left
      cx + i, cy + i, // bottom right
      tft.color565(i, i, i));
  }
 
  return micros() - start;
}
 
unsigned long testFilledTriangles() {
  unsigned long start, t = 0;
  int           i, cx = tft.width()  / 2 - 1,
                   cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(cx,cy); i>10; i-=5) {
    start = micros();
    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(0, i*10, i*10));
    t += micros() - start;
    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(i*10, i*100));
    yield();
  }
 
  return t;
}
 
unsigned long testRoundRects() {
  unsigned long start;
  int           w, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  w     = min(tft.width(), tft.height());
  start = micros();
  for(i=0; i<w; i+=6) {
    i2 = i / 2;
    tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 00));
  }
 
  return micros() - start;
}
 
unsigned long testFilledRoundRects() {
  unsigned long start;
  int           i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(tft.width(), tft.height()); i>20; i-=6) {
    i2 = i / 2;
    tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
    yield();
  }
 
  return micros() - start;
}


로드된 소스는 Adafruit shield 사용을 전제로 작성된 소스이므로 위와 같이 24~33번 라인을 수정한다.


컴파일하고 업로드하면 그래픽이 표시된다.









실행해 보면 생각만큼 빠르지는 않다. 아두이노 전용은 아니지만 STM32, ESP8266, ESP32를 위한 더 빠른 라이브러리가 있다. 아두이노에도 적용 가능하지 않을까싶다. 아래 링크를 참고하자.

TFT_eSPI


반응형
Posted by J-sean
:
반응형

약 6년전, 동생이 구매했던 노트북이 있다. 삼성 NT900X3G. 지금도 간단한 문서 작업이나 인터넷, 영화 감상용으로는 부족함 없는 노트북이지만 6년이라는 시간동안 많은 일이 있었던 모양이다. 이제는 키보드의 몇몇 키가 눌리지 않고 디스플레이 힌지는 한쪽이 부서져 덜렁거린다. 그 외 컴퓨터라는 기기의 역할에 문제는 없지만 낡아버린 모습에 더 이상 애착이 가지 않았던거 같다. 창고 한쪽 구석에 쳐박혀 버리질 날만 기다리던 이 녀석을 구해 왔다. 조카들에게 괜찮은 장난감으로 바꿔주겠다는 약속을 남기고..

 

이런 스펙의 노트북이라고 한다.

 

우선 노트북 커버를 제거하고 덜렁거리는 디스플레이 및 배터리를 분리한다. 그리고 전원을 연결해 작동 여부를 테스트한다. 그 동안은 KODI를 설치해 영화감상용으로 사용했다.

 

2020/02/01 - [General] - 삼성 노트북 분해, SSD 조립 하기

 

 

영상: 라즈베리 파이 홈미디어 센터(KODI) 만들기

 

주요 부품이 있는 하판을 분리하자. (왼쪽 하단에 2014.01.21이 적혀 있다. 6년 전 구매한 노트북이라는 증거가 될 수 있지 않을까?)

 

프레임, 키보드, 터치패드등 불필요한 부분을 제거하고 작동에 필요한 부분만 남겼다. 디스플레이도 프레임을 제거하려고 했지만 액정 뒤에 붙은 백라이트가 프레임에 접착되어 있어 분리가 불가능했다.

 

 

분리한 부품들만으로 작동 테스트를 해 본다. USB 키보드를 연결하니 입력도 문제 없다. 지금은 스피커가 분리되어 있다.

 

스피커를 연결하고 영상을 플레이하니 소리도 잘 나온다.

 

오락실 게임을 설치하기 위한 소프트웨어 작업을 진행 한다.

운영체제는 라즈비안을 설치 했다. 운영체제 설치 후 레트로 파이를 설치한다.

 

2020/02/13 - [Raspberry Pi & Arduino] - Raspberry Pi Desktop(Debian), Ubuntu에서 RetroPie 설치하기

 

동네 오락실 분위기가 나려면 오락기가 있어야 한다. 진짜 오락실에 설치되어 있는 오락기 사이즈로 만들면 부담스러우므로 테이블에 올려 놓고 사용할 만한 사이즈로 디자인 한다.

전체 디자인은 라즈겜동의 도면을 기본으로, 분해한 노트북에 맞도록(세트 1) 수정했다.

 

 

디자인한 파일을 목재 가공소에 보내서 견적을 받고 작업을 시작 했다.

(가공소에 도착 했을때 진행 중이던 작업. 내가 의뢰한 제품은 아니다)

 

일반 MDF는 접착제에서 포름알데히드가 나오기 때문에 친환경 자재인 컬러보드(블랙)를 사용했다. 덕분에 단가는 거의 2배가 되었지만 석탄같은 색깔 때문이었을까? 자연에 조금 더 가까워지는 느낌을 얻을 수 있었다.

 

가공이 잘 되었는지 확인하기 위해 가조립 해본다. 별 문제 없는거 같다.

 

조이스틱과 버튼을 설치한다.

 

2020/04/09 - [Review] - DIY Sanwa Arcade Joystick Kit - DIY 산와 아케이드 조이스틱 키트

 

 

엔코더와 케이블을 연결한다.

 

그럴듯해 보인다.

 

나사를 이용해 나무판들을 고정한다. 나사에 맞는 드릴 비트가 없어 조심히 작업했지만 모서리 가까운곳에서는 약간씩 갈라졌다. 순간접착제로 보강해준다.

 

뒷판은 쉽게 열고 닫을 수 있도록 경첩을 달아 준다. 오른쪽 경첩의 나사 하나가 부러져 적당히 고정만 시켰다.

노트북 전원 단자도 문제 없이 나온다.

 

 

뒷판이 고정 될 수 있도록 자석 도어 캐치를 달아준다. (설치하고 보니 좀 약하다)

 

노트북 기판에서 디스플레이까지 연결되는 케이블과 전원 단자 케이블은 충분히 길지는 않지만 문제가 되지는 않았다. 하지만 전원 버튼은 기판에 붙어 있기 때문에 오락기 케이스 외부로 빼내기 위해 케이블에 납땜하고 연장 해야했다. (빨간색, 검정색 케이블과 노란색 푸시버튼)

 

작업한 노트북 기판을 오락기 내부에 설치한다. (대충.. 쇼트나지 않도록 적당히 잘 넣는다)

 

디스플레이도 노출된 회로를 적당히 처리하고 붙여준다.

 

 

오른쪽엔 코인기를 설치하기 위한 구멍이 있다.

 

이 코인기를 설치한다.

 

생각해 보니 조카들의 반발이 예상되어 일단 그냥 막아둔다.

 

이제 뒷문을 닫고 노트북 어댑터를 연결한다.

 

 

미리 설치해둔 운영체제와 레트로 파이가 문제없이 작동된다. 노란색 푸시버튼은 문제가 있어 다른 디자인의 검정색 푸시버튼으로 바꿨다. 푸시버튼 양 옆으로 노트북에서 분리한 스피커를 설치하기 위한 네모난 홈이 보인다. 하지만 스피커가 케이스 내부에 있어도 소리가 잘 들리므로 그냥 두기로 한다. (스피커를 케이스 밖으로 빼려면 케이블을 잘라서 연장해야 하는데 그게 귀찮아서 그랬던건 아니다) 

 

메탈 슬러그도 잘 된다.

 

스트리트 파이터도 잘 된다.

 

컬러보드도 표면이 거칠다보니 약간의 마무리 작업이 필요하다. 조카들에게 주기전에 시트지를 붙이거나 바니쉬를 발라줘야겠다. 조립하기 전에 미리 했으면 좋았을텐데..

 

반응형
Posted by J-sean
:
반응형

분당의 많은 아파트가 90년대 초에 지어졌다. 이제 그 아파트들은 내부 자재/기기가 노후되어 제기능을 못 하는 경우가 많은데, 덕분에 한 아파트 내에서도 두어달에 한 집씩은 내부 인테리어를 진행 한다는 안내문이 붙고 며칠 후 큰 소음을 내며 공사가 진행되곤 한다.


물론 우리집도 예외는 아니다. 벽지는 변색되어 몇 년 전에 전체 도배를 새로 했으며 화장실에서 물을 쓰면 어디선가 삐~ 하는 소리가 들려오곤 한다. 겨울철 내 방의 보일러는 무조건 24시간 가동되는 등 크고 작은 문제점들이 많이 발생하고 있다. 한 집에서 오랫동안 살아 오며 하나 둘 발생하는 고장이라 그런 걸까? 그런 현상들이 너무나도 자연스럽게 생활의 일부가 되어 버리고 문제라 생각치 못하게 되는 문제가 문제이다(?)


어쨌든 어릴적 처음 이 아파트로 이사 왔을 때 참 신기했던 장치가 하나 있다. 문 밖에서 서 있는 사람을 화면으로 볼 수 도 있고 아파트 경비실로 전화도 걸 수 있으며 화재, 가스등의 경보도 해 주던, 흔히 인터폰이라고 불리는 인터컴(도어폰)이 신기했을 뿐 아니라 새 집에 이사온 느낌을 한층 배가시켜 주었었다. 벨을 누른 사람도 없는데 괜히 화면을 켜서 작은 모니터를 통해 문 밖 세상을 바라보게 만들기도 했으니 말이다.


꺼져있는 거실의 인터컴. 이젠 얘도 나이가 많다.


그런 인터컴이 이젠 더 이상 작동 하지 않는다. 언제부터 전원이 꺼져 있었는지는 기억도 나지 않고, 몇 달 전 오븐에 피자를 굽다 작은 불을 냈을땐 화려한 조명 마냥 검은 연기가 온 집안을 따뜻하게 감쌌지만 어떤 장치에서도 경보를 해 주지 않는걸 확인 하며 이 집에서 믿을 건 우리 가족 밖에 없다는 걸 다시 한 번 확인 했다.


그러다 더 이상 쓰지도 않고 새로 바꾸고 싶지도 않은 인터컴이 지저분해 보였다. 그냥 깔끔하게 떼버리려 했으나 드러나게 될 인터컴의 뒷 공간때문에 잠시 망설이다 뭔가 비슷하게 꾸며야겠다는 생각이 들었다.


우선 다이소로 달려 갔다.


다이소에서 3,000원 주고 구입해 온 코르크 보드.


10.1인치 LCD 디스플레이를 대본다.


양 옆에 작은 스피커를 달면 귀여울거 같다. 사진에 보이는건 스피커 커버.



이게 스피커(뒷 부분). (3W X 2EA)


대충 잘라 내야 할 부분을 따라 그렸다.


자르고 보니 안쪽은 싸구려 스티로폼이다. 부서진 스티로폼 조각이 막 날린다. 난 분명히 코르크 보드를 샀는데...


모니터와 스피커 커버를 대본다. 모니터는 보드 뒤에 대려고 했는데 아무래도 앞으로 보내야 할 거 같다.



전체적으로 모양이 나쁘지 않다.


글루건으로 고정 한다.


고정 했다.


모니터 AD 보드(Analog to Digital Board)와 (리모콘)컨트롤 보드도 붙여 준다. 오른쪽 케이블이 전원 케이블이다.



글루건이 이것 저것 잘 붙여 준다.


모니터가 잘 나오는지 확인 한다.


설치에 문제가 없는지 확인하기 위해 인터컴을 제거한 벽에 대본다.

문제 없을리가 없다. 스피커 때문에 벽에 안들어 간다. 먼저 확인 했어야 했는데... 그래... 한 번에 될리가 없지...


모니터 아래로 위치를 바꾼다. 스피커를 뗀 자리에 큰 구멍이 두 개 남았다. 후......



전원 공급을 위해 AC to DC 컨버터를 두 개 준비 한다. (220ACV → 5DCV 2A)

한 개는 라즈베리 파이용, 다른 한 개는 모니터와 앰프용이다.

라즈베리 파이는 전원 버튼이 없기 때문에 종료 후 전원 차단을 위한 스위치와 모니터 전원 공급용 터미널도 준비 했다. (모니터 구매 시 받은 터미널은 USB 타입이다)


케이블을 연결하고 글루건으로 고정 한다.


앞면을 보니 그럴 듯 하다. 옆에 튀어 나온건 모니터 (리모콘)컨트롤 보드


라즈베리 파이에 사용할 운영체제를 준비 한다. 집 안의 다른 컴퓨터와 연결 될 수 있도록 네트워크, Samba, VNC등도 세팅 한다.


2020/01/16 - [Raspberry Pi & Arduino] - Raspberry Pi Raspbian 설치 후 업데이트, 한글, 고정 IP, VNC, Samba 설정



지저분한 케이블을 정리 하자.


사용하지 않는 신호 케이블은 모두 정리하고 전원 공급용 220ACV 케이블만 따로 빼서 AC to DC Converter에 연결 한다.


라즈베리 파이를 연결 하고 벽에 붙여 전원을 넣었다. 폭발 하지 않았다. 다행이다.

이것 저것 실행해 본다.


무선 인터넷으로 연결 되어 유튜브도 잘 나온다.



모니터 양 옆의 포스트잇은 신경 쓰지 말자. 무언가를 가리기 위한 것은 아니다.


손님이 놀러 오면 사진을 띄우고 음악을 틀어 준다. (feat. 조카들)


키보드와 마우스를 연결 할 수 도 있지만 거실 벽에 설치 되어 있는 라즈베리 파이에 사용하기는 불편하므로 안쓰는 스마트폰을 무선으로 연결해 컨트롤 한다.


반응형
Posted by J-sean
:
반응형

2020/08/14 - [Raspberry Pi & Arduino] - How to play old DOS games on KODI(LibreELEC) with Raspberry Pi - 코디(라즈베리 파이)에서 도스 게임 플레이 하기


LibreELEC은 미디어 센터 프로그램인 KODI를 위한 리눅스 운영체제이다. KODI는 윈도우즈, 안드로이드등 여러가지 운영체제를 지원 하지만 라즈베리 파이를 이용한 홈 미디어 센터를 구성할때 KODI가 구동 될 수 있는 최소한의 환경을 갖춘 LibreELEC으로 진행 하면 다른 운영체제로 진행 하는 것보다 원활한 동작이 가능 하다.


LibreELEC - https://libreelec.tv/


KODI - https://kodi.tv/



Raspberry Pi - https://www.raspberrypi.org/


설치 및 활용은 영상으로 확인 하자.


Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc.

Rufus - https://rufus.ie/


반응형
Posted by J-sean
:
반응형

가끔 조카들이 놀러 오면 같이 놀기 위해 오래된 컴퓨터에 레트로파이를 설치하고 예전 오락실 게임이나 콘솔 게임을 플레이 할 수 있도록 만들었다. 


2020/02/13 - [Raspberry Pi] - Raspberry Pi Desktop(Debian), Ubuntu에서 RetroPie 설치하기


이 컴퓨터는 거실에 두고 모니터보다 훨씬 큰 TV에 연결 했으니 이렇게만 만들어도 충분히 게임을 즐길 수 있지만 왠지 예전 게임기 느낌이 살지는 않는거 같아 살짝 아쉬운 마음이 들었다. 그래서 구입한 RETROFLAG의 SUPERPi Case-J.


제조: RETROFLAG

판매: Amazon


공식 판매처인 미국 아마존에서 구입이 가능하지만 게임패드가 포함되지 않은 모델의 경우에도 제품과 배송비를 합쳐 약 $26의 비용이 든다. 국내에서 사는게 더 비싸다면 배송 기간도 고려해서 아마존 구매를 생각해 보겠지만 디바이스마트에서 \16,500에 파는걸 보고 바로 주문했다.


그리고 이틀 후 도착한 내 소중한 케이스...


상자 앞 면


상자 뒷 면


상자 옆 면


겉 상자를 열면 안에 다시 속 상자가 들어 있다.



속 상자에 들어 있는 케이스. 모든 부품이 케이스 안에 다 들어 있다.


케이스 뒷 면


조립 메뉴얼


조립 메뉴얼



상자 안에 들어 있는 부품들


라즈베리 파이를 조립하기 전에 SD 카드를 분리해야 한다. 굳이 분리할 필요가 있을까 생각 했지만 분리하지 않으면 라즈베리 파이가 케이스에 제대로 들어가지 않는다.


조립에 필요한 부품들


케이스 위에 설치 할 롬 카트리지. 진짜 롬 카트리지는 아니고 SD 카드를 보관 할 수 있는 케이스다.



드라이버가 포함되어 있다.


Power/Reset/SAFE SHUTDOWN 스위치, 전면 USB포트 연결 케이블, GPIO연결 커넥터등이 보인다.





설치 과정 영상 추가 예정..................

SAFE SHUTDOWN 설치 영상 추가 예정............






영상에서 볼 수 있듯이 SAFE SHUTDOWN기능은 터미널에서 아래 명령어만 입력해 주면 간단히 설치 가능 하다.


wget -O - "https://raw.githubusercontent.com/RetroFlag/retroflag-picase/master/install.sh" | sudo bash


참고로 레트로파이에서 키보드 설정을 바꾸지 않았다면 영국 키보드로 지정되어 있다. 우리가 일반적으로 사용하는 키보드와는 키배열이 약간 다르므로 아래 그림을 참고 하자.


영국 키보드


그럼 install.sh에는 어떤 내용이 있어 SAFE SHUTOWN 기능이 설치 되는지 살펴 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/bin/bash
 
 
#Step 1) Check if root--------------------------------------
if [[ $EUID -ne 0 ]]; then
   echo "Please execute script as root." 
   exit 1
fi
#-----------------------------------------------------------
 
#Step 2) enable UART----------------------------------------
cd /boot/
File=config.txt
if grep -"enable_uart=1" "$File";
    then
        echo "UART already enabled. Doing nothing."
    else
        echo "enable_uart=1" >> $File
        echo "UART enabled."
fi
#-----------------------------------------------------------
 
#Step 3) Update repository----------------------------------
sudo apt-get update -y
#-----------------------------------------------------------
 
#Step 4) Install gpiozero module----------------------------
sudo apt-get install -y python3-gpiozero
#-----------------------------------------------------------
 
#Step 5) Download Python script-----------------------------
cd /opt/
sudo mkdir RetroFlag
cd /opt/RetroFlag
script=SafeShutdown.py
 
if [ -e $script ];
    then
        echo "Script SafeShutdown.py already exists. Doing nothing."
    else
        wget "https://raw.githubusercontent.com/RetroFlag/retroflag-picase/master/SafeShutdown.py"
fi
#-----------------------------------------------------------
 
#Step 6) Enable Python script to run on start up------------
cd /etc/
RC=rc.local
 
if grep -"sudo python3 \/opt\/RetroFlag\/SafeShutdown.py \&" "$RC";
    then
        echo "File /etc/rc.local already configured. Doing nothing."
    else
        sed --"s/^exit 0/sudo python3 \/opt\/RetroFlag\/SafeShutdown.py \&\n&/g" "$RC"
        echo "File /etc/rc.local configured."
fi
#-----------------------------------------------------------
 
#Step 7) Reboot to apply changes----------------------------
echo "RetroFlag Pi Case installation done. Will now reboot after 3 seconds."
sleep 3
sudo reboot
#-----------------------------------------------------------




스크립트 분석 추가 예정..................






그럼 Safeshutdown.py의 내용을 확인해 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python3
from gpiozero import Button, LED
import os 
from signal import pause
 
powerPin = 3 
resetPin = 2 
ledPin = 14 
powerenPin = 4 
hold = 1
led = LED(ledPin)
led.on()
power = LED(powerenPin)
power.on()
 
#functions that handle button events
def when_pressed():
  led.blink(.2,.2)
  os.system("sudo killall emulationstation && sleep 5s && sudo shutdown -h now")
def when_released():
  led.on()
def reboot(): 
  os.system("sudo killall emulationstation && sleep 5s && sudo reboot")
  
btn = Button(powerPin, hold_time=hold)
rebootBtn = Button(resetPin)
rebootBtn.when_pressed = reboot 
btn.when_pressed = when_pressed
btn.when_released = when_released
pause()




스크립트 분석 추가 예정......







반응형
Posted by J-sean
:
반응형

RetroPie installed on a PC can be too fast to play retro games. You can adjust(slow down) its speed by changing video_frame_delay value.


라즈베리 파이가 아닌 PC에 레트로파이를 설치한 경우 성능 차이로 인해 레트로 게임들이 너무 빨라 진행 할 수 가 없다. video frame delay 설정을 변경해 속도를 조절해 보자.


RetroPie Configuration을 선택 한다.


Configuration Editor를 선택 한다.


Advanced Configuration을 선택 한다.


Configure Libretro options를 선택 한다.



all/retroarch.cfg를 선택 한다.


video_frame_delay를 선택 한다.


Edit를 선택 한다.


15 이하의 적당한 숫자를 입력 하고 OK를 선택 한다. 다시 게임을 진행해 보면 속도가 적당히 변경되어 있다.



Configure Libretro options가 아닌 Manually edit RetroArch configurations에서도 변경 가능 하다.


all/retroarch.cfg를 선택 한다.


원래는 video_frame_delay가 주석처리(#)되어 있는데 위와 같이 주석을 삭제하고 적당한 값으로 바꾸면 된다.


특정 게임에서 잠시 video frame delay 값을 변경하고 싶다면 Hotkey(Select) + X 를 누른다.



Quick Menu가 표시 된다. 라즈베리파이(라즈비안)가 한국어로 설정되어 있다면 Quick Menu의 글자가 제대로 표시되지 않는다. 언어 설정을 영어로 바꾸면 제대로 표시된다.


Latency를 선택 한다.


Frame Delay를 선택 한다.


원하는 값을 선택 하고 게임으로 돌아가면 변경된 값이 적용 된다. 이 방법은 일회성이며 게임을 다시 시작하면 원래 값으로 돌아 간다. 이 상태를 저장하고 싶다면 Quick Menu에서 Save State를 선택 한다.


반응형
Posted by J-sean
:
반응형

레트로파이는 보통 레트로파이 홈페이지에서 받은 이미지를 MicroSD 카드에 설치하고 라즈베리 파이에서 사용 한다.

하지만 라즈비안이 설치된 라즈베리 파이나 라즈베리파이 데스크탑(데비안)이나 우분투가 설치된 PC에서도 레트로파이를 설치하고 레트로 게임을 즐길 수 있다.


2020/01/16 - [Raspberry Pi & Arduino] - Raspberry Pi Raspbian 설치 후 업데이트, 한글, 고정 IP, VNC, Samba 설정

2020/02/14 - [Raspberry Pi & Arduino] - How to slow down RetroPie games - 레트로파이 게임 속도 조절 하기(video frame delay)

2021/01/24 - [Raspberry Pi & Arduino] - How to add Korean font, game marquees, images, videos, and descriptions to RetroPie - 레트로파이에 한글 폰트, 게임 마키, 이미지, 플레이 영상, 설명 넣기

2020/11/12 - [Vita] - 오래된 노트북을 오락실 게임기로 만들어 보자.


APT repository를 모두 업그레이드 하고 Git이 설치 되어 있지 않다면 설치 한다.


sudo apt-get update

sudo apt-get upgrade

sudo apt-get install git


RetroPie-Setup 스크립트를 다운로드 한다.


git clone --depth=1 https://github.com/RetroPie/RetroPie-Setup.git


다운 받은 스크립트 디렉토리로 이동하고 retropie_setup.sh를 실행 한다.


sudo ./retropie_setup.sh


Basic install을 실행 한다.


Yes를 선택 하고 설치를 진행 한다.



꽤 오랫동안 설치가 진행 된다.


설치가 완료되면 빌드하지 못한 에뮬레이터에 대한 메세지가 몇 개 표시 된다. 모두 OK를 선택 한다.


Setup 화면으로 돌아 오면 Update를 진행 한다.


Yes를 선택 하고 설치된 패키지 업데이트를 진행 한다.


최신 버전의 RetroPie Setup Script를 가져 왔다. OK를 선택 한다.



업데이트를 계속 진행 한다.


RetroPie에 관한 간단한 메세지가 표시 된다. OK를 선택 한다.


Kernel등의 underlying OS package들을 업데이트하기 위해 Yes를 선택 한다.


다시 꽤 오랜 시간동안 설치가 진행 된다.


업데이트가 완료 되었다.



재부팅을 선택 한다.


Yes를 선택 한다.


재부팅이 완료되면 레트로파이를 실행 한다. 터미널에서 emulationstation 명령어를 실행 해도 된다.


아래 게임패드 다이어그램을 참고하여 컨트롤러 버튼 설정을 진행 한다. 게임패드가 없다면 위와 같은 화면이 나오지만 키보드로 진행할 수 도 있다.


SNES Controller


XBox 360 Controller


PS3 Controller



버튼 설정을 완료하면 레트로파이가 실행 된다. 아직은 아무 게임도 보이지 않는다. 이 상태에서 게임 롬을 설치해도 오디오 드라이버가 설정 되지 않아 아무 소리도 나지 않는다. 오디오 드라이버 설정을 위해 A 버튼을 눌러 RetroPie Configuration으로 들어 간다.


Configuration Editor를 선택 한다.


Advanced Configuration을 선택 한다.


Configure Libretro options를 선택 한다.


all/retroarch.cfg를 선택 한다.



audio_driver를 선택 한다.


alsa(Advanced Linux Sound Architecture)를 선택 하고 Configuration을 빠져나가 레트로파이를 종료 한다.

※ 아래 순서로 진행해도 된다.

RetroPie Configuration - Retroarch - Settings - Audio - Output - Audio - alsa

RetroPie Configuration - Retroarch - Settings - Drivers - Audio - alsa


/home/pi/RetroPie/roms/arcade 디렉토리에 게임 롬 파일을 복사 한다. Raspberry Pi 2/3에 추천하는 MAME emulator는 lr-mame2003이고 lr-mame2003 emulator에 사용 가능한 게임 롬 버전은 MAME 0.78이다. MAME 0.78용 스트리트 파이터 2 롬 파일을 복사 했다.


다시 레트로 파이를 실행하면 ARCADE가 활성화 되고 1개의 게임이 사용 가능하다는 메세지가 표시 된다. A 버튼을 눌러 선택 한다.


ARCADE를 선택 하면 위에서 복사한 스트리트 파이터 2가 표시 된다. A 버튼을 누르고 진행 한다.



기본 에뮬레이터를 선택 하는 화면이 표시 된다. lr-mame2003을 선택 한다.


스트리트 파이터 2가 launching 된다.



스트리트 파이터 2가 실행 된다.


기본적으로 Raspberry Pi Desktop은 Screen Saver 프로그램이 설치되어 있지 않다. 하지만 Screen Saver 기능은 활성화 되어 있기 때문에 사용자 입력이 없으면 10분 후 화면이 꺼진다. RetroPie를 사용하는 동안에도 키보드나 마우스가 아닌 게임패드를 사용한다면 사용자 입력이 없다고 판단해 Screen Saver가 작동하게 되고 화면이 꺼져버리게 된다.


Preferences - Add/Remove Software를 선택 한다.


xscreensaver를 검색하고 설치 한다.


다시 Preferences를 확인해 보면 Screensaver가 설치되어 있다.


Screen Saver를 실행 한다.



Mode 콤보 박스를 클릭 하고 Disable Screen Saver를 선택 한다.


Screen Saver 기능이 비활성화 된다.


컴퓨터를 켜거나 재부팅하면 항상 위와 같은 GRUB 화면이 나온다. 여기서 몇 초(5초) 기다리거나 엔터키를 한 번 눌러야 부팅이 시작된다. 바로 부팅 되도록 해보자.


/etc/default/grub 파일을 열자.



GRUB_TIMEOUT=5로 되어 있다. 그래서 5초를 기다려야 했던 것이다.


기다리지 않고 바로 부팅되도록 0으로 바꾸고 저장한다.


sudo update-grub 명령으로 업데이트 한다. 이제 기다릴 필요 없이 바로 부팅된다.


반응형
Posted by J-sean
: