[Make]/MicroController

Raspberry Pi

Maker_H 2025. 3. 2. 13:31
반응형

라즈베리파이 시작하기

터미널 명령어

`cd` : 상위로 폴더로 이동
`cd home/pi/파일폴더이름` : 폴더 이동 
`ls` : 현재 폴더의 파일 보기

sd카드 포맷
[RASP | SD카드 포맷, 복제 및 용량 확장](https://velog.io/@sz3728/RASP-SD카드-복제-및-용량-확장)

sd카드에 RASP OS 넣어주기.
라즈베리파이 사이트에서 OS 다운 및 설치
sd카드 연결

라즈베리파이 끄는 법
메뉴에서 로그아웃 선택해서 끄고 전부 해체한다.

초기 세팅

  • 패키지 업데이트
    • 항상 터미널에서 패키지 파일을 받기 전, 패키지 업데이트
$ sudo apt-get update
$ sudo apt-get upgrade



한글설정
[RASP | Fcitx 설치, 한글 설정 및 키보드 한영 전환](https://velog.io/@sz3728/RASP-Fcitx-설치-한글-설정-및-키보드-한영-전환)



기본 정보

라즈베리파이 5 나옴.

라즈베리 파이 쇼트 조심
라즈베리 파이 보드에 전원을 넣기 전 마우스, 키보드, 모니터 등을 꼽고 전원을 꽂아야 쇼트가 나지 않는다.

전원은 무조건 마지막에 연결.

  • [GPIO 고장나는 경우](https://velog.io/@amos42/%EB% 9D% BC% EC% A6%88% EB% B2% A0% EB% A6% AC% ED% 8C% 8C% EC% 9D% B4-GPIO-%EB% B3% B4% ED%98% B8-%EB% B0% A9% EB% B2%95)
    • INPUT 모드인 상태에서 VCC와 직결
    • OUTPUT 모드인 상태에서 GND와 직결
    • GPIO에 3.3V를 초과한 과전압이 흐를 때
    • 각 GPIO 핀의 허용 전류 이상이 흐를 때
    • 전체 GPIO로 흐르는 전류의 총합이 허용 전류 이상일 때

전원 5 볼트


40 Pin 정보

GPIO를 사용할 땐 전원과 연결 필요 없이 GPIO 핀에 바로 꼽기만 하면 됨. GPIO, GND만 연결되면 됨.

 

참고. [Raspberry Pi4 GPIO Pinout 완벽 정리](https://fishpoint.tistory.com/7687)

 

BCM과 Physical pin 넘버

라즈베리파이 터미널에서 GPIO 번호 확인하기 $ gpio readall

출처 : ChatGPT
내가 이해한 내용 : Physical은 라즈베리파이에 핀이 40개가 있고 그걸 순서대로 1,2,3... 번호를 매겨둔 것이다.
BCM : 각 피지컬 번호를 GPIO에 할당시켜 직접 코드에서 사용하는 번호이다. 따라서 BCM의 번호를 코드에 사용하면 된다. BCM은 개발자가 임의로 바꿀 수 없다. 
MODE : IN, OUT 입, 출력 상태를 나타냄.
V : 전원의 On(1), Off(0)를 나타냄.
pi@yahboom4wd:~ $ gpio readall
 +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 |  OUT | 1 |  3 || 4  |   |      | 5v      |     |     |
 |   3 |   9 |   SCL.1 |   IN | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 1 | ALT0 | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | ALT0 | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 1 | 11 || 12 | 1 | IN   | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |  OUT | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |  OUT | 0 | 15 || 16 | 0 | OUT  | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 1 | OUT  | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI | ALT0 | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO |  OUT | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK |  OUT | 0 | 23 || 24 | 1 | OUT  | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 0 | IN   | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 0 | OUT  | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 0 | 31 || 32 | 1 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |  OUT | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 |  OUT | 0 | 35 || 36 | 0 | OUT  | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |  OUT | 0 | 37 || 38 | 0 | OUT  | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | OUT  | GPIO.29 | 29  | 21  |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+



RPi.GPIO 입,출력

GPIO 핀의 설정을 입력 또는 출력 하나로만 지정이 가능. 

setup(), 핀의 Mode, 즉 입, 출력 상태 설정하기.
initial : 초기상태 0 또는 1

GPIO.setup(pin_no, GPIO.IN(또는 OUT), initial=GPIO.LOW(또는 HIGH))

 



저항

저항(R) 구하기.
R = V/I(A)


참고. [[아두이노 기초 강좌] 6. 저항 색상표로 저항 크기 읽는 법 (저항 색띠 읽는 법)](https://blog.naver.com/roboholic84/220304850807)


 


GPIO

LED 켜기

import RPi.GPIO as GPIO

led_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)
GPIO.output(led_pin, True)
try:
    while True:
        pass

except KeyboardInterrupt :
    pass

GPIO.cleanup()



LED 2초 뒤에 끄기

import RPi.GPIO as GPIO
Import time

led_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)
GPIO.output(led_pin, True)
time.sleep(2.0)
GPIO.output(led_pin, False)

GPIO.cleanup()



LED 깜빡이기

import RPi.GPIO as GPIO
Import time

led_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)

try :
    while True :
        GPIO.output(led_pin, True)
        time.sleep(2.0)
        GPIO.output(led_pin, False)
        time.sleep(2.0)
except KeyboardInterrupt :
    pass

GPIO.cleanup()


참고. [라즈베리 파이 40 PIN 정리](https://fishpoint.tistory.com/7687)



PWM

40핀 레이아웃 참고, 펄스폭 변조라고 하며 0V와 5V를 적절히 사용하여 평균값으로 아날로그 신호를 대체한다.
주파수가 높을수록 빠르게 변화한다.
참고. [PWM LED 제어하기](https://minimax95.tistory.com/entry/PWM-LED-%EC%A0%9C%EC%96%B4%ED%95%98%EA%B8%B0)
import RPi.GPIO as GPIO

led_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)

pwm = GPIO.PWM(led_pin, 1.0) #1.0Hz, 1초동안
pwm.start(50.0) # 0.0~100.0, High 구간은 50프로로 시작.

try :
    while True :
        pass

except KeyboardInterrupt :
    pass

pwm.stop()
GPIO.cleanup()


밝기 및 속도 조절, 천천히 밝아짐.

import RPi.GPIO as GPIO
import time

led_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)

try :
    while True:
        for t_high in range(0,11) :
            cnt = 0
            while True :
                GPIO.output(led_pin, True)
                time.sleep(t_high * 0.001)
                GPIO.output(led_pin, False)
                time.sleep((10 - t_high) * 0.001)

                cnt += 1
                if cnt == 10 : break

except KeyboardInterrupt :
    pass

GPIO.cleanup()



ChangeDuttyCycle

import RPi.GPIO as GPIO
import time

led_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)

pwm = GPIO.PWM(led_pin, 1000.0)
pwm.start(0.0)

try :
    while True :
        for t_high in range(0, 101) :
            pwm.ChangeDuttyCycle(t_high)
            time.sleep(0.01)
        for t_high in range(100, -1, -1) :
            pwm.ChangeDuttyCycle(t_high)
            time.sleep(0.01)

except KeyboardInterrupt :
    pass

pwm.stop()
GPIO.cleanup()



원격 접속 및 데이터 전송

원격 접속(터미널)
1. 기본 설정 -> 라즈베리파이 환경설정 -> 인터페이스 -> SSH, VNC ON -> 확인

 

Window
- Putty 프로그램으로 접속할 수 있게 환경 만들기 : 터미널을 통해 윈도에서 RASP을 컨트롤 가능
[TheKoguryo's 기술 블로그](https://thekoguryo.github.io/oci/chapter03/5/2/)

Macbook
- 터미널에서 `$ SSH@RASP의 IP주소`만 치면 진입 가능 

데이터 송수신
Window는 winSCP 사이트에서 프로그램 다운로드하기

해당 프로그램을 통해 RASP와 window에 있는 파일을 서로 공유 가능하다.
[winSCP](https://winscp.net/eng/download.php)
디폴트 ID : pi, PW : raspberry

 

맥북은 CyberDuck 프로그램 사용

  • 프로그램을 열어 새 연결을 클릭
  • 프로토콜을 SFTP(SSH File Transfer Protocol)로 변경
  • 서버에 IP 주소 입력, 사용자 이름 pi, 비밀번호 yahboom 입력
  • IP주소는 연결된 와이파이마다 다름.


버튼연결

GPIO08, 07번 사용. 
08번 스위치 연결법

  • 3V 사용(1번) - 저항 10k - GPIO 8번으로 연결 - 버튼 - GND 

07번 스위치 연결법
위와 같지만 저항은 GPIO 7번으로 연결



부저 사용

LED 위치에 대신 적용, 저항 필요 없음.
부저 `+` 부분이 전원과 연결



모터 돌리기

빨간색 - 전원 5v
오렌지 - signal(pin18번과 연결)
갈색 - GND



코드에 작성되는 점퍼 선 번호는 GPIO에 있는 번호를 작성해야 함.
GND 같은 애들은 코드에 따로 작성을 안 하니 상관없음.



Thread, 스레드

뜻은 실을 의미하지만 프로그래밍에서 멀티태스킹이 가능하도록 해준다.
각 스레드에 작업을 걸어 두기에 많은 양의 작업을 동시에 진행할 경우 버벅거린다.
라즈베리 파이로 예를 들면 LED가 깜빡거리는 동시에 컴퓨터 화면상에 print가 된다.
반드시 `import threading`을 하여 사용해야 여러 기능 사용이 가능하다.
메인 프로그램을 주로 하고 시간이 날 때 스레드에 있는 요청을 불러와 기능하기에 반응이 느리다.


thread 예제. Python Idle에서 사용.

import threading
import time

flag_exit = False
def t1_main():
while True:
print("\tt1")
time.sleep(0.5)
if flag_exit: break

t1 = threading.Thread(target=t1_main)
t1.start()

try:
while True:
print("main")
time.sleep(1.0);

except KeyboardInterrupt:
pass

flag_exit = True
t1.join()

 




Window와 Raspberry Pi 서버 연결하기

윈도에서 `JK_Comm.exe` 해당 프로그램 실행
RASP에서 `Server.py` 파일 실행 후 서버단의 IP주소를 코드에 변경한다. (서버단은 RASP이니까 RASP IP주소 입력)
RASP은 서버단이라 윈도(클라이언트)에서 먼저 메시지를 보내야 응답이 가능.
RASP이 클라이언트인 경우 `Client.py` 파일 사용 (서버단은 Win이니까 Win IP주소 입력)
Window 명령 프롬프트에서 ipconfig를 입력하여 IP주소를 알 수 있다.



chattering

소프트웨어적으로는 문제없음. 하드웨어적 문제.
신호가 끊겨 스위치를 누를 때 값이 제멋대로 변경되는 사항을 의미.
신호가 끊기는 시간을 랜덤임. 따라서 실험을 해보고 타임 딜레이를 줘야 함. (너무 길면 반응이 없으니 적당히 조절할 것.)


time.sleep 적용 전

import RPi.GPIO as IoPort
def DisplayState(St): #.....................(1)
  if St == 1:
    IoPort.output(Led1,False)
    IoPort.output(Led2,False)
  elif St == 2:
    IoPort.output(Led1,True)
    IoPort.output(Led2,False)
  elif St == 3:
    IoPort.output(Led1,False)
    IoPort.output(Led2,True)
  else:
    IoPort.output(Led1,True)
    IoPort.output(Led2,True)

Key1 = 8
Led1 = 18
Led2 = 23
IoPort.setmode(IoPort.BCM)
IoPort.setup(Led1, IoPort.OUT)
IoPort.setup(Led2, IoPort.OUT)
IoPort.setup(Key1, IoPort.IN)

State = 1
while State <= 4: #.....................(2)
  DisplayState(State) #.....................(3)
  while True: #.....................(4)
    if IoPort.input(Key1)== False:
      break
  while True: #.....................(5)
    if IoPort.input(Key1)== True:
      break
  State += 1 #.....................(6)
DisplayState(1) #.....................(7)


time.sleep 적용 후

import RPi.GPIO as IoPort
import time
def DisplayState(St):
  global State #....................(1)
  if St == 1:
    IoPort.output(Led1,False)
    IoPort.output(Led2,False)
  elif St == 2:
    IoPort.output(Led1,True)
    IoPort.output(Led2,False)
  elif St == 3:
    IoPort.output(Led1,False)
    IoPort.output(Led2,True)
  else:
    IoPort.output(Led1,True)
    IoPort.output(Led2,True)
    State = 0 #....................(2)
Key1 = 8
Led1 = 18
Led2 = 23
IoPort.setmode(IoPort.BCM)
IoPort.setup(Led1, IoPort.OUT)
IoPort.setup(Led2, IoPort.OUT)
IoPort.setup(Key1, IoPort.IN)

State = 1
while State <= 4:                         
  DisplayState(State)
  while True:                                   
    if IoPort.input(Key1)== False:
      break
  time.sleep(0.1) #....................(3)
  while True:                                   
    if IoPort.input(Key1)== True:
      break
  time.sleep(0.1) #....................(4)
  State += 1





초음파 센서

TRIG : GPIO23, 송신 모듈
ECHO : GPIO24, 수신 모듈
TRIG에서 초음파 근접 신호를 잡으면 ECHO까지 걸리는 시간을 계산하여 알 수 있다.
참고. https://rasino.tistory.com/349



openCV 활용 웹캠 사용하기

참고. https://supersfel.tistory.com/305

라즈비안 GUI에서 카메라 설정이 안 보이는 문제 발생.

  • 카메라 연결 후 `$ lsusb`로 정상 연결 확인.
  • 카메라 설정이 라즈베리파이 환경설정 > 인터페이스에 떠야 하는데 안 뜸.
  • [찾다 보니 gpu가 문제인걸 앎. 최소 128mb가 되어야 카메라 사용가능](https://raspberrypi.stackexchange.com/questions/68927/why-raspberry-pi-camera-wont-appear-on-rasp-config)
  • 하지만 gpu 설정하는 창인 환경설정 > 퍼포먼스에 gpu설정이 안 보임.
  • `$ sudo raspi-config`에서도 없음.
  • 터미널에 `$ vcgencmd get_mem arm;vcgencmd get_mem gpu` 입력 후 확인하니 gpu값이 뜸.
  • `$ sudo nano /boot/config.txt` 입력 후 arm_64bit=1 밑에다 `gpu_mem=128`이라고 작성함.
  • `$ vcgencmd get_mem gpu` 확인 결과 gpu 메모리 128mb로 변경되어 있음.
  • 하지만 세팅에 카메라가 뜨지 않음.

 

[카메라 세팅법](https://youtu.be/OEGR19aE0dg?si=qRJJf9rqz100zp-S)

# 카메라 프로그램 설치
$ sudo apt install fswebcam

# 캡쳐 명령어 테스트
$ fswebcam -r 1280x270 --no-banner /home/pi/image1.jpg

# openCV 설치
$ pip3 install opencv-python



openCV 모듈 찾기 에러 발생.

[xternally-managed 삭제](https://www.jeffgeerling.com/blog/2023/how-solve-error-externally-managed-environment-when-installing-pip3)
error: externally-managed-enviroment

$ sudo rm -rf /usr/lib/python3.11/EXTERNALLY-MANAGED

# opencv 재설치 OK
$ pip3 install opencv-python



비디오카메라 테스트

참고. https://raspberrypi-guide.github.io/electronics/using-usb-webcams

 

아래 카메라 실행코드 `.py` 파일로 작성 후 노트북 저장. > RASP 다운로드 폴더로 옮김.

import cv2

cam = cv2.VideoCapture(0)

while True:
ret, image = cam.read()
cv2.imshow('Imagetest',image)
k = cv2.waitKey(1)
if k != -1:
break
cv2.imwrite('/home/pi/testimage.jpg', image)
cam.release()
cv2.destroyAllWindows()



RASP 터미널에서 카메라 실행

$ python3
>>> import sys
>>> sys.path.append('/home/pi/Downloads')
>>> import camera.py





라즈베리파이 화면 사이즈 수정하기

옵션 들어가기

$ sudo raspi-config


> Display Options

 

> Resolution

 

> 원하는 해상도 선택 후 재부팅

반응형