반응형

기본 정렬 알고리즘 세 가지(퀵, 머지, 힙)를 파이게임으로 시각화 해 보자.

 

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
import os
import random
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'= '1'
import pygame
from math import ceil, floor
 
pygame.init()
pygame.display.set_caption("Sorting Visualization")
screensize = (640580)
screen = pygame.display.set_mode(screensize)
clock = pygame.time.Clock()
framerate = 10
running = True
 
font = pygame.font.Font(None30)
text = font.render("Sorting Visualization\n\n" +
                   "*q: Quick Sorting [ O(nlogn) ]\n" +
                   "*m: Merge Sorting [ O(nlogn) ]\n" +
                   "*h: Heap Sorting [ O(nlogn) ]\n" +
                   "\n*g: Random Data Generation"True"gray")
text_pos = text.get_rect()
text_pos.center = (screen.get_width()/2, text_pos.height/2)
 
data_size = 64
data = list()
data_color = list()
 
def DataGenerator():
    global data
    global data_color
    
    data = [random.randint(10400for i in range(data_size)]
    data_color = [(random.randint(0255), random.randint(0255), random.randint(0255))
                  for i in range(data_size)]
    
DataGenerator()
 
def Visualize():
    screen.fill("black")
    screen.blit(text, text_pos)
    for i in range(data_size):
        pygame.draw.rect(screen, data_color[i], (i*10, screensize[1]-data[i], 10, data[i]))
    pygame.display.flip()
    clock.tick(framerate)
 
def Finalize():
    screen.fill("white")
    pygame.display.flip()
    clock.tick(framerate)
 
def EventHandler():
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            return -1
        elif event.type == pygame.QUIT:
            exit()
 
def QuickSort(start, end):
    if start >= end:
        return
    pivot = start
    left = start + 1
    right = end
    
    while left <= right:
        if EventHandler() == -1:
            return
        
        while left <= end and data[left] <= data[pivot]:
            left += 1
        while right > start and data[right] >= data[pivot]:
            right -= 1            
        if left > right:
            data[right], data[pivot] = data[pivot], data[right]
            data_color[right], data_color[pivot] = data_color[pivot], data_color[right]
        else:
            data[left], data[right] = data[right], data[left]
            data_color[left], data_color[right] = data_color[right], data_color[left]
            
        Visualize()
            
    QuickSort(start, right-1)
    QuickSort(right+1, end)
 
def MergeSort_1(data_list, color_list):
    if len(data_list) < 2:        
        return data_list, color_list
    
    mid = len(data_list) // 2
    low_data_list, low_color_list = MergeSort_1(data_list[:mid], color_list[:mid])
    high_data_list, high_color_list = MergeSort_1(data_list[mid:], color_list[mid:])
    
    merged_data_list = list()
    merged_color_list = list()
    l = h = 0
    while l < len(low_data_list) and h < len(high_data_list):
        if low_data_list[l] < high_data_list[h]:
            merged_data_list.append(low_data_list[l])
            merged_color_list.append(low_color_list[l])
            l += 1
        else:
            merged_data_list.append(high_data_list[h])
            merged_color_list.append(high_color_list[h])
            h += 1
            
    merged_data_list += low_data_list[l:]
    merged_color_list += low_color_list[l:]
    
    merged_data_list += high_data_list[h:]
    merged_color_list += high_color_list[h:]
    
    return merged_data_list, merged_color_list
 
def MergeSort_2():
    def sort(low, high):
        if EventHandler() == -1:
            return
        
        if high - low < 2:
            return
        
        mid = (low + high) // 2
        sort(low, mid)
        sort(mid, high)
        merge(low, mid, high)
 
    def merge(low, mid, high):
        data_temp = list()
        color_temp = list()
        l, h = low, mid
        
        while l < mid and h < high:
            if data[l] < data[h]:
                data_temp.append(data[l])
                color_temp.append(data_color[l])
                l += 1
            else:
                data_temp.append(data[h])
                color_temp.append(data_color[h])
                h += 1
                
        while l < mid:
            data_temp.append(data[l])
            color_temp.append(data_color[l])
            l += 1
            
        while h < high:
            data_temp.append(data[h])
            color_temp.append(data_color[h])
            h += 1
            
        for i in range(low, high):
            data[i] = data_temp[i - low]
            data_color[i] = color_temp[i - low]
            
            Visualize()            
 
    sort(0, data_size)
 
def HeapSort():
    for i in range(len(data)):
        par = ceil(i/2- 1
        while par >= 0 and data[par] < data[i]:
            data[par], data[i] = data[i], data[par]
            data_color[par], data_color[i] = data_color[i], data_color[par]
            i = par
            par = floor((i-1)/2)
 
    for i in range(len(data)-10-1):
        data[0], data[i] = data[i], data[0]
        data_color[0], data_color[i] = data_color[i], data_color[0]
 
        cur = 0
        lch = 1
        rch = 2
        
        while True:
            if EventHandler() == -1:
                return
        
            if rch < i and data[lch] < data[rch]:
                lch = rch
                
            if lch < i and data[lch] > data[cur]:
                data[lch], data[cur] = data[cur], data[lch]
                data_color[lch], data_color[cur] = data_color[cur], data_color[lch]
                
                Visualize()
                
                cur = lch
                lch = cur * 2 + 1
                rch = cur * 2 + 2
            else:
                lch = i # break와 같은 효과
                
            if not lch < i:
                break
            
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_q:
            QuickSort(0, data_size - 1)
            Finalize()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_m:
            MergeSort_2()
            Finalize()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_n:
            data, data_color = MergeSort_1(data, data_color)
            Finalize()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_h:
            HeapSort()
            Finalize()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_g:
            DataGenerator()
            
   Visualize()
 

 

코드를 작성하고 실행한다.

 

 

※ 참고

2024.03.09 - [Python] - [Pygame] Sorting Algorithms in Python 파이썬 정렬 알고리즘 1

 

알고리즘_05_강의록.pdf
3.91MB
알고리즘_04_강의록.pdf
1.86MB

 

 

 

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

토양 수분 센서를 라즈베리 파이와 함께 사용해 보자.

 

라즈베리 파이는 아날로그 신호를 입력 받을 수 없기 때문에 ADC(MCP3008)를 사용해야 한다.

 

Analog-Digital Converter

 

라즈베리 파이 - ADC - 토양 수분 센서를 연결한다.

 

 

ADC            -       Raspberry Pi

VDD                                5V
VREF                               5V
AGND                            Ground
CLK                           GPIO11(SCLK)
DOUT                         GPIO9(MISO)
DIN                            GPIO10(MOSI)
CS/SHDN                    GPIO8(CE0)
DGND                            Ground

 

Soil Moisture Sensor   -   ADC(Raspberry Pi)

VCC                                       (5V)

GND                                    (Ground)

A0                                         CH0

 

라즈베리 파이에서 raspi-config를 실행한다.

 

 

3 Interface Options를 선택한다.

 

I4 SPI를 선택한다.

 

YES를 선택한다.

 

SPI가 활성화 된다.

 

 

git이 설치되어 있지 않다면 설치한다.

 

py-spidev를 다운 받는다.

 

다운받은 py-spidev 디렉토리로 이동하고 설치한다

 

수분량을 감지하는 소스를 입력하고 저장한다.

 

 

소스를 실행하면 센서에서 읽은 값이 표시된다.

※ 참고

Python Spidev

 

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

리눅스(우분투, 라즈베리 파이)에서 특정 프로그램이 자동 실행 되도록 해 보자.

 

/etc/rc.local 파일에 실행하고 싶은 명령을 추가한다.

위 예제는 루트 디렉토리(/)의 파일 목록을 /home/sean/test.txt 파일로 출력한다.

'exit 0' 명령 위에 추가한다.

 

/lib/systemd/system/rc-local.service 파일을 열어준다.

 

아래 명령을 추가한다.

[Install]

WantedBy=multi-user.target

 

서비스를 활성화한다.

 

 

재부팅 해보면 rc.local 파일이 자동 실행되어 ~/test.txt 파일이 생성돼 있다.

 

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

라즈베리 파이 피코는 컴퓨터에 연결 하고 전원을 공급한 상태에서 소스를 입력하고 실행(F5)해야 프로그램이 작동한다. 컴퓨터 연결 없이 자동으로 실행되도록 해 보자.

 

소스를 입력하고 파일명을 main.py로 Pico에 저장한다.

이제 컴퓨터 없이도 피코 LED가 깜빡인다. MicroPython은 전원 공급시 자동으로 파일 시스템에서 main.py를 찾아 실행한다. (Headless Operation)

 

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

 

 

Raspberry Pi Pico를 사용해 보자.

 

Pico를 컴퓨터에 연결하면 기타 장치 - RP2 Boot로 인식된다.

 

파일 익스플로러에서도 확인 할 수 있다. (RPI-RP2)

만약 파일 익스플로러에 Pico가 표시되지 않는다면 BOOTSEL 버튼을 누른 상태에서 컴퓨터에 연결한다.

 

MicroPython을 설치하기 위해 아래 링크에 접속해 MicroPython UF2 파일을 다운로드한다.

Raspberry Pi Documentation

 

MicroPython is a full implementation of the Python 3 programming language that runs directly on embedded hardware like Raspberry Pi Pico. You get an interactive prompt (the REPL) to execute commands immediately via USB Serial, and a built-in filesystem. The Pico port of MicroPython includes modules for accessing low-level chip-specific hardware.

 

 

다운로드한 UF2 파일을 Pico(RPI-RP2)에 복사해 넣는다.

 

한 쪽 구석에 디바이스 설정 중이라는 메세지가 나타난다.

 

설정이 끝나면 기타 장치였던 Pico는 USB 직렬 장치(COMX)로 표시된다.

 

Thonny를 다운로드하고 설치한다.

Thonny

 

 

Thonny를 실행한다.

 

Run - Select interpreter...를 클릭한다.

 

MicroPython (Raspberry Pi Pico)와 USB 직렬 장치(COMX)를 선택한다.

 

간단한 소스를 입력하고 Run 버튼(F5)을 클릭한다.

 

 

소스를 어디에 저장할지 물어 보면 Raspberry Pi Pico를 선택한다.

 

적당한 이름을 지정한다.

Run 버튼을 클릭했으므로 소스가 저장되고 나면 바로 실행된다.

Pico에 달려있는 LED(GP25)가 1초 간격으로 깜빡인다.

 

LED(GP25)

 

Pico를 다시 연결하면 아무것도 실행되지 않는다. File - Open...을 클릭한다.

 

 

Raspberry Pi Pico를 선택한다.

 

Pico에 저장되어 있는 소스를 선택하고 실행한다.

 

WAVESHARE의 Pico-like MCU, RP2040-Zero도 같은 방식으로 동작한다.

RP2040-Zero는 Raspberry Pi Pico와 Pinout이 다르고 단색 LED가 아닌 WS2812 RGB LED(GP16)가 사용되었다.

단색 LED가 아니기 때문에 간단한 Blink.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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import time
from machine import Pin
import rp2
 
max_lum =100
r=0
g=0
b=0
 
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
    T1 = 2
    T2 = 5
    T3 = 3
    wrap_target()
    label("bitloop")
    out(x, 1)               .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
    jmp("bitloop")          .side(1)    [T2 - 1]
    label("do_zero")
    nop()                   .side(0)    [T2 - 1]
    wrap()
 
 
# Create the StateMachine with the ws2812 program, outputting on Pin(4).
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(16))
 
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)
 
# Color change
while True:
    for i in range(0,max_lum):
        r=i
        b=max_lum-i
        rgb =(g<<24| (r<<16| (b<<8)
        sm.put(rgb)
        time.sleep_ms(10)
    time.sleep_ms(300)
    for i in range(0,max_lum):
        g=i
        r=max_lum-i
        rgb =(g<<24| (r<<16| (b<<8)
        sm.put(rgb)
        time.sleep_ms(10)
    time.sleep_ms(300)
    for i in range(0,max_lum):
        b=i
        g=max_lum-i
        rgb =(g<<24| (r<<16| (b<<8)
        sm.put(rgb)
        time.sleep_ms(10)
    time.sleep_ms(300)
 

 

조금 복잡한 WS2812 Test Code로 RGB값 변화를 확인할 수 있다.

 

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

최신 버전의 OpenCV를 리눅스나 라즈베리 파이에 설치하기 위해서는 길고 지루한 과정을 거쳐야 한다. 꼭 최신 버전의 OpenCV가 필요한게 아니라면 간단하게 설치하고 사용해 보자.

 

libopencv-dev를 설치한다.

 

3.2.0 버전의 OpenCV가 설치 되었다.

 

텍스트 편집기에서 간단한 소스를 입력하고 저장한다.

 

컴파일 한다. pkg-config 명령어를 감싸고 있는 ` 기호는 Tab 키 위에 있는 backtick이다.

 

 

컴파일된 파일을 실행하면 라즈베리 파이에 연결된 카메라가 작동되고 sample.jpg가 생성된다.

 

sample.jpg

 

라즈베리 파이가 아닌 PC(우분투)에서 위 내용을 진행하면 opencv2/opencv.hpp가 없다는 에러가 발생하게 된다.

 

설치한 libopencv-dev의 버전이 다르기 때문인데 PC(우분투)에서는 라즈베리 파이보다 높은 버전의(4.2.0) opencv가 설치된다.

 

 

pkg-config --list-all 명령으로 확인된 opencv4 옵션을 사용해 컴파일 한다.

 

반응형
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
: