반응형

레트로파이를 업데이트 하고 나면 부팅시 자동 로그인 되지 않고 암호를 물어보는 경우가 생긴다. 아래와 같이 자동 로그인 옵션을 활성화 하자.

 

Raspberry Pi Software Configuration Tool을 실행하고 3 Boot Options를 선택한다.

 

B1 Desktop / CLI 를 선택한다.

 

B2 Console Autologin을 선택한다.

 

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

레트로파이에 한글 폰트, 게임 마키, 이미지, 플레이 영상, 설명등을 넣어 보자.

 

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

 

특별한 설정을 하지 않았다면 레트로파이(아케이드)에 게임 이름 정도만 표시된다. 등록된 게임을 잘 아는 사람은 문제 없겠지만 모르는 사람은 무슨 게임인지 알 수가 없다. 처음 하는 사람도 어떤 게임인지 알 수 있도록 이미지, 플레이 영상, 설명등을 넣어 보자.

 

Cabin-Bold.ttf 가 기본(영문) 폰트다. 한글이 표시 될 수 있도록 원하는 한글 폰트(KATURI.TTF)를 /etc/emulationstation/themes/carbon/art/ 에 복사한다. 

 

/etc/emulationstation/themes/carbon/ 에 있는 'carbon.xml', 'theme.xml' 파일에 설정된 폰트를 변경한다.

 

두 파일을 열고 'Cabin-Bold.ttf'가 나오는 부분을 모두 한글 폰트 이름(KATURI.TTF)으로 바꾼다. (원래 있던 'Cabin-Bold.ttf' 파일을 지우고 한글 폰트 이름을 'Cabin-Bold.ttf'로 바꾸면 두 파일의 내용을 바꾸지 않아도 된다)

 

 

RetroPie를 실행해 보면 바뀐 폰트가 적용되어 있다.

 

/opt/retropie/configs/all/emulationstation/gamelists/arcade/gamelist.xml 에 게임 이름, 이미지, 플레이 영상, 설명등을 등록 할 수 있다.

 

gamelist.xml
5.73MB

 

아래와 같은 형식으로 작성 한다.

 

<?xml version="1.0"?>

<gameList>

<game>

<path>게임 파일 경로</path>

<name>게임 이름</name>

<image>게임 이미지 파일 경로</image>

<video>게임 플레이 영상 파일 경로</video>

<marquee>게임 마키 파일 경로</marquee>

<developer>게임 제작사</developer>

<publisher>게임 판매사</publisher>

<genre>게임 장르</genre>

<players>게임 플레이어 수</players>

<releasedate>게임 발매일</releasedate>

<desc>게임 설명</desc>

</game>

<game>

...

</game>

...

</gameList>

 

'gamelist.xml'에 등록한 파일 경로 및 이름대로 marquee, snap, video 디렉토리를 /home/pi/RetroPie/roms/arcade/ 에 생성하고 각 디렉토리에 맞는 파일을 복사한다.

 

 

마키(marquee)

 

이미지(image)/스냅(snap)

 

영상(video)

 

 

예를 들어 marquee 디렉토리의 내용은 위와 같다.

 

RetroPie를 실행해 보자. ARCADE - 메탈 슬러그의 마키, 플레이 영상, 게임 설명등이 디스플레이 된다.

 

스트리트 파이터 2의 내용도 잘 디스플레이 된다.

 

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

라즈베리 파이 카메라를 이용해 실시간 영상 스트리밍을 해 보자.


실시간 영상 스트리밍은 기본 설치되어 있는 cvlc(command-line vlc)를 이용한다. 만약 vlc가 설치되어 있지 않다면 설치하고 위 명령어를 입력한다.


위와 같이 대기 상태가 된다. (명령어 끝에 &를 붙여주면 백그라운드로 실행 할 수 있다)


다른 컴퓨터(우분투)에서 VLC를 실행한다. Media - Open Network Stream... 을 선택하고 '라즈베리파이 IP 주소:9000/'을 입력하면 스트리밍된 영상이 플레이 된다.


윈도우에서도 VLC를 설치하면 영상을 플레이 할 수 있다.


■ raspivid 옵션

  • -t, --timeout: Time (in ms) to capture for. If not specified, set to 5s. Zero to disable

  • -d, --demo: Run a demo mode (cycle through range of camera options, no capture)

  • -fps, --framerate: Specify the frames per second to record

  • -k, --keypress: Cycle between capture and pause on ENTER

  • -w, --width: Set image width <size>

  • -h, --height: Set image height <size>

  • -o, --output: Output filename <filename> (to write to stdout, use '-o -'). If not specified, no file is saved

  • -v, --verbose: Output verbose information during run

  • -cs, --camselect: Select camera <number>. Default 0

  • -p, --preview: Preview window settings <'x,y,w,h'>

  • -f, --fullscreen: Fullscreen preview mode

  • -op, --opacity: Preview window opacity (0-255)

  • -n, --nopreview: Do not display a preview window

  • -dn, --dispnum: Display on which to display the preview window (dispmanx/tvservice numbering)

  • -sh, --sharpness: Set image sharpness (-100 to 100)

  • -co, --contrast: Set image contrast (-100 to 100)

  • -br, --brightness: Set image brightness (0 to 100)

  • -sa, --saturation: Set image saturation (-100 to 100)

  • -ISO, --ISO: Set capture ISO

  • -rot, --rotation: Set image rotation (0, 90, 180, or 270)

  • -hf, --hflip: Set horizontal flip

  • -vf, --vflip: Set vertical flip

  • -roi, --roi: Set region of interest (x,y,w,d as normalised coordinates [0.0-1.0])

  • -a, --annotate: Enable/Set annotate flags or text

  • -ae, --annotateex: Set extra annotation parameters (text size, text colour(hex YUV), bg colour(hex YUV), justify, x, y)


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

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


중국에서 구매한 라즈베리 파이용 카메라가 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
:
반응형

L293D는 다이오드가 내장된 DC모터 드라이버다.


L293D DC Motor Driver


L293D Pin Map

Enable 1, 2와 Enable 3, 4는 PWM(0~255)으로 모터 속도를 제어한다.

모터가 높은 전압을 사용한다면 Vcc 2에 외부 전원을(4.5~36V) 연결한다. (Vcc 1은 내부 로직용 전압이다)


Peak output current(nonrepetitive, t ≤ 100 µs): 1.2A

Continuous output current: 600mA

l293d.pdf


드라이버 내부에는 모터에서 발생하는 역기전력으로 인한 MCU 손상 방지용 다이오드가 내장되어 있다.

GND(4, 5, 12, 13)는 모두 연결되어 있어서 하나만 외부 GND에 연결하면 된다.



위 다이어그램과 같이 연결한다.


L293D - Arduino

Enable 1, 2 - D8

Input 1 - D9

Output 1 - Motor +

GND - GND

Output 2 - Motor -

Input 2 - D10

Vcc 2 - 5V

Vcc 1 - 5V




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
#define EN1 8
#define IN1 9
#define IN2 10
 
void setup() {
  pinMode(EN1, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
}
 
void loop() {
  digitalWrite(EN1, HIGH);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  delay(1000);
 
  digitalWrite(EN1, LOW);
  delay(1000);
 
  digitalWrite(EN1, HIGH);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  delay(1000);
 
  digitalWrite(EN1, LOW);
  delay(1000);
}


위 코드를 컴파일하고 아두이노에 업로드한다. 'CW 회전 - 1초 대기 - CCW 회전 - 1초 대기'가 반복된다.


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

RFID-RC522 모듈과 아두이노를 이용해 RFID카드를 읽고 쓸 수 있다.


RFID-RC522


RFID Cards


위 다이어그램과 같이 연결한다.


ARDUINO - RFID-RC522

3.3V - 3.3V

D9 - RST

GND - GND

N/A - IRQ

D12 - MISO

D11 - MOSI

D13 - SCK

D10 - SDA



Library Manager에서 MFRC522을 검색하고 설치한다.


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
#include <SPI.h>
#include <MFRC522.h>
 
#define SS_PIN 10
#define RST_PIN 9
 
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
 
// Array for new NUID 
byte nuidPICC[4= {0};
 
void setup() {
  Serial.begin(9600);
  SPI.begin(); // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522
}
 
void loop() {
  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if (!rfid.PICC_IsNewCardPresent()) {
    delay(500);
    
    return;
  }
 
  // Verify if the NUID has been read.
  if (!rfid.PICC_ReadCardSerial()) {
    delay(500);
    
    return;
  }
 
  if (rfid.uid.uidByte[0!= nuidPICC[0||
    rfid.uid.uidByte[1!= nuidPICC[1||
    rfid.uid.uidByte[2!= nuidPICC[2||
    rfid.uid.uidByte[3!= nuidPICC[3] ) {
    Serial.println("A new card has been detected.");
 
    // Store NUID into nuidPICC array
    for (byte i = 0; i < 4; i++) {
      nuidPICC[i] = rfid.uid.uidByte[i];
    }
  } else {
    delay(500);
 
    return;
  }
 
  Serial.print("PICC type: ");
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  Serial.println(rfid.PICC_GetTypeName(piccType));
 
  // Check if classic MIFARE type
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println("Your tag is not MIFARE Classic type.");
    
    return;
  }
 
  Serial.print("Card UID: ");
  for (byte i = 0; i < 4; i++) {
    Serial.print(rfid.uid.uidByte[i]);
    if (i < 3)
      Serial.print("-");
  }
  Serial.println();
}


RFID 카드 읽기 소스를 컴파일 하고 아두이노에 업로드한다. 


RFID-RC522 모듈에 카드를 가까이 대면 카드 타입과 ID가 표시된다.


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

아두이노로 간단히 RF433MHz 통신이 가능하다.


왼쪽이 리시버, 오른쪽이 트랜스미터다.


송신기와 수신기를 아두이노에 연결해 준다. RadioHead Packet Radio library를 다운받고 아래와 같이 아두이노 라이브러리에 복사한다.


특별한 설치 과정은 없다. 그냥 복사한다.


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
// ask_transmitter.pde
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to transmit messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) transmitter with an TX-C1 module
// Tested on Arduino Mega, Duemilanova, Uno, Due, Teensy, ESP-12
 
#include <RH_ASK.h>
#ifdef RH_HAVE_HARDWARE_SPI
#include <SPI.h> // Not actually used but needed to compile
#endif
 
RH_ASK driver;
// RH_ASK driver(2000, 4, 5, 0); // ESP8266 or ESP32: do not use pin 11 or 2
// RH_ASK driver(2000, 3, 4, 0); // ATTiny, RX on D3 (pin 2 on attiny85) TX on D4 (pin 3 on attiny85), 
// RH_ASK driver(2000, PD14, PD13, 0); STM32F4 Discovery: see tx and rx on Orange and Red LEDS
 
void setup()
{
  #ifdef RH_HAVE_SERIAL
    Serial.begin(9600);    // Debugging only
  #endif
    if (!driver.init())
  #ifdef RH_HAVE_SERIAL
      Serial.println("init failed");
  #else
      ;
  #endif
    else
      Serial.println("init succeeded");
}
 
void loop()
{
  const char *msg = "Hello Wireless World!";
 
  driver.send((uint8_t *)msg, strlen(msg));
  driver.waitPacketSent();
  #ifdef RH_HAVE_SERIAL
      Serial.println("Message sent.");
  #endif
  
  delay(200);
}


Transmitter 소스를 컴파일하고 아두이노에 업로드한다.



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
// ask_receiver.pde
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to receive messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) receiver with an Rx-B1 module
// Tested on Arduino Mega, Duemilanova, Uno, Due, Teensy, ESP-12
 
#include <RH_ASK.h>
#ifdef RH_HAVE_HARDWARE_SPI
#include <SPI.h> // Not actually used but needed to compile
#endif
 
RH_ASK driver;
// RH_ASK driver(2000, 4, 5, 0); // ESP8266 or ESP32: do not use pin 11 or 2
// RH_ASK driver(2000, 3, 4, 0); // ATTiny, RX on D3 (pin 2 on attiny85) TX on D4 (pin 3 on attiny85), 
// RH_ASK driver(2000, PD14, PD13, 0); STM32F4 Discovery: see tx and rx on Orange and Red LEDS
 
void setup()
{
  #ifdef RH_HAVE_SERIAL
    Serial.begin(9600);    // Debugging only
  #endif
    if (!driver.init())
      
  #ifdef RH_HAVE_SERIAL
      Serial.println("init failed");
  #else
      ;
  #endif
    else
      Serial.println("init succeeded");
}
 
void loop()
{
  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
  memset(buf, 0, RH_ASK_MAX_MESSAGE_LEN);
  uint8_t buflen = sizeof(buf);
 
  if (driver.recv(buf, &buflen)) // Non-blocking
  {
    // Message with a good checksum received, dump it.
    driver.printBuffer("Got:", buf, buflen);
    #ifdef RH_HAVE_SERIAL
      String message = (char*)buf;
      Serial.print("Message: ");
      Serial.println(message);
    #endif
  }
 
  delay(200);
}


Receiver 소스를 컴파일하고 아두이노에 업로드한다.


송신기에서는 계속 메세지를 보낸다.


송신기에서 보낸 메세지를 수신기에서 받는다. printBuffer()로 출력한 메세지는 각 문자의 아스키 코드값이다.


void RHGenericDriver::printBuffer(const char* prompt, const uint8_t* buf, uint8_t len)

Parameters

[in] prompt string to preface the print

[in] buf Location of the buffer to print

[in] len Length of the buffer in octets.


Prints a data buffer in HEX. For diagnostic use


※ 참고: RH_ASK Class Reference


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

DFPlayer Mini MP3 Player For Arduino를 이용해 아두이노로 MP3 파일을 재생할 수 있다.


마이크로 SD 카드보다 약간 크다.


DFPlayer Mini Pin Map


Pin Description


배터리, 스피커, 푸시버튼을 연결해 아두이노 없이도 사용할 수 있다.


Specifications

  • supported sampling rates (kHz): 8/11.025/12/16/22.05/24/32/44.1/48

  • 24 -bit DAC output, support for dynamic range 90dB, SNR support 85dB

  • fully supports FAT16, FAT32 file system, maximum support 32G of the TF card, support 32G of U disk, 64M bytes NORFLASH

  • a variety of control modes, I/O control mode, serial mode, AD button control mode

  • advertising sound waiting function, the music can be suspended. when advertising is over in the music continue to play

  • audio data sorted by folder supports up to 100 folders, every folder can hold up to 255 songs

  • 30 level adjustable volume, 6 -level EQ adjustable


위 다이어그램과 같이 연결한다. MP3 파일 재생시 노이즈가 심하다면 RX에 1KΩ 저항을 연결한다.



아두이노IDE - Library manager에서 DFRobotDFPlayerMini를 검색하고 설치한다.


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
/***************************************************
DFPlayer - A Mini MP3 Player For Arduino
 <https://www.dfrobot.com/product-1121.html>
 
 ***************************************************
 This example shows the basic function of library for DFPlayer.
 
 Created 2016-12-07
 By [Angelo qiao](Angelo.qiao@dfrobot.com)
 
 GNU Lesser General Public License.
 See <http://www.gnu.org/licenses/> for details.
 All above must be included in any redistribution
 ****************************************************/
 
/***********Notice and Trouble shooting***************
 1.Connection and Diagram can be found here
 <https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
 2.This code is tested on Arduino Uno, Leonardo, Mega boards.
 ****************************************************/
 
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
 
SoftwareSerial mySoftwareSerial(1011); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
 
void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  
  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true){
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));
  
  myDFPlayer.volume(20);  //Set volume value. From 0 to 30
  myDFPlayer.play(1);  //Play the first mp3
}
 
void loop()
{
  static unsigned long timer = millis();
  
  if (millis() - timer > 30000) {
    timer = millis();
    myDFPlayer.next();  //Play next mp3 every 30 second.
  }
  
  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }
}
 
void printDetail(uint8_t type, int value){
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
  
}


위 소스를 컴파일하고 업로드하면 모든 노래가 30초씩 플레이된다.


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
bool begin(Stream& stream, bool isACK = truebool doReset = true);
bool waitAvailable(unsigned long duration = 0);
bool available();
uint8_t readType();
uint16_t read();
void setTimeOut(unsigned long timeOutDuration);
void next();
void previous();
void play(int fileNumber=1);
void volumeUp();
void volumeDown();
void volume(uint8_t volume);
void EQ(uint8_t eq);
void loop(int fileNumber);
void outputDevice(uint8_t device);
void sleep();
void reset();
void start();
void pause();
void playFolder(uint8_t folderNumber, uint8_t fileNumber);
void outputSetting(bool enable, uint8_t gain);
void enableLoopAll();
void disableLoopAll();
void playMp3Folder(int fileNumber);
void advertise(int fileNumber);
void playLargeFolder(uint8_t folderNumber, uint16_t fileNumber);
void stopAdvertise();
void stop();
void loopFolder(int folderNumber);
void randomAll();
void enableLoop();
void disableLoop();
void enableDAC();
void disableDAC();
int readState();
int readVolume();
int readEQ();
int readFileCounts(uint8_t device);
int readCurrentFileNumber(uint8_t device);
int readFileCountsInFolder(int folderNumber);
int readFileCounts();
int readFolderCounts();
int readCurrentFileNumber();


그 외 다른 기능은 DFRobotDFPlayerMini.h를 참고한다.


※ 제작사 홈페이지를 보면 아래와 같은 문구가 있다.


NOTE: The order you copy the mp3 into micro SD card will affect the order mp3 played, which means play(1) function will play the first mp3 copied into micro SD card.


파일명을 0001.mp3, 0002.mp3... 이런식으로 변경해서 SD카드에 넣어도 play(1) 함수 실행 시 0001.mp3가 아닌, 제일 먼저 복사된 파일이 첫 번째로 재생되는거 같다.


반응형
Posted by J-sean
: