참고한 책 : 진짜 코딩하며 배우는 라즈베리파이 4
IoT
구성요소
Sensors/Device
Network
Platform
BIg Data
Application/Service
라즈베리파이 os 설치
커스텀 img 파일 다운
커스텀 파일(이미지) 사용하여 sd카드에 설치(imager_1.6.2.exe 실행)
Storage - sd카드 선택 - wirte
img : 리눅스 기반 커스텀 파일
라즈베리파이에 랜선으로 연결해 아이피를 타고 들어가 접속하는 방식
sd카드 - boot 드라이브
command line.txt => 끝에 ip=192.168.138.100 추가
ssh 파일 추가(확장자명 x)
라즈베리파이의 sd카드, 랜선, 전원 모두 연결
노트북을 공유기처럼 사용(내부 네트워크를 구성할 수 있음)
(원래는 공유기에 노트북과 라즈베리파이를 각각 연결하는 게 맞으나 공사가 덜 끝난 관계로...)
네트워크 연결 보기
WI-FI 속성 - 공유 항목 둘다 체크, 홈 네트워킹 연결 : 이더넷
이더넷 - 인터넷 프로토콜 버전4(TCP/IPv4) : 다음 IP 주소 사용 설정(IP주소 192.168.138.1)
주의! 이더넷 연결 꼭 확인할 것(전원 콘센트가 불안정하여 전원이 꺼질 수 있음)
PuTTY
HostName에 192.168.138.100 입력 후 Open 클릭
Login as: pi
~password : raspberry(입력한 문구 안보임 주의)
라즈베리파이에 접속 완료
리눅스 기본 명령어
ls : 파일과 디렉토리 목록을 보여줌(= 윈도우의 파일탐색기) / 다양한 옵션이 있음(-a, -l -r 등, -al처럼 같이 써도 됨)
pwd : 현재 작업중인 디렉토리 확인 가능(print working directory)
tree : 디렉토리 구조를 트리 모양으로 출력
cd : 디렉토리 이동
cd 위치 적을 때 앞글자만 치고 tap 누르면 있는 폴더의 경우 자동완성 됨(home일 경우 h, tap)
touch 파일명 : 파일 생성
rmdir 디렉토리명 : 빈 디렉토리 삭제(파일 있으면 삭제 안됨)
rm 파일명 : 파일 삭제
rm -r 디렉토리명 : 해당 디렉토리와 파일 삭제
rm -r : 디렉토리와 함께 파일까지 삭제 가능(현재 어디 위치인지 매우 주의해서 사용해야함)
cat 파일명 : 파일 내용 확인
vi 파일명 : 리눅스 기본 에디터 => i 누르면 편집 가능
nano 파일명 : nano 에디터
VSCode 사용
라즈베리파이의 파이썬 패키지 사용
예외 처리
try:
while True:
print("Hello. I'm Raspberry Pi")
except KeyboardInterrupt: # ctrl+c 강제종료하면 그냥 멈추겠다
pass
time.sleep
import time
try:
while True:
print("Hello. I'm Raspberry Pi")
time.sleep(0.5)
except KeyboardInterrupt:
pass
데이터 타입/연산/리스트
num = 2
print(num) # 2
print(type(num)) # <class 'int'>
a = 1
b = 2
sum = a+b
print(sum) # 3
print(17/3) # 5.666666666666667
print(type(17/3)) # <class 'float'>
print(17//3) # 5 : 몫 출력
print(17%3) # 2 : 나머지 출력
# 리스트
L = ["python", 1,2,3,4, "last"]
print(L[0]) # python
print(L[1]) # 1
print(L[2]) # 2
print(L[1:3]) # [1, 2] : 1부터 3까지
print(L[5][1]) # a : 5번째의 1번 인덱스
L.append(4) # 맨뒤에 한 개 추가
L.append(5)
print(len(L)) # 8 : 길이 확인(length)
print(L) # ['python', 1, 2, 3, 4, 'last', 4, 5]
L.extend([12, 35])
print(len(L)) # 10
print(L) # ['python', 1, 2, 3, 4, 'last', 4, 5, 12, 35]
파이썬 수행 속도 측정
import time
start = time.time() # 현재 시간을 얻어와 start 변수에 저장
cnt = 0
while True: # 반복
cnt = cnt+1 # cnt 변수를 하나 증가
if cnt>10000000: # cnt 변수 값이 10000000보다 크면
break # 10줄로 이동
end = time.time() # 현재 시간을 얻어와 end 변수에 저장
print(cnt) # 10000001 : cnt 변수 값 출력
print(end - start) # 9.522742748260498 : 천만번 수행하는데 걸리는 시간
논리 연산자 / 비교연산자
# 논리 연산자
print(True and True)
print(True and False)
print(False or True)
print(False or False)
print(not False)
print(not True)
'''
True
False
True
False
True
False
'''
# 비교 연산자
print(4 == 4)
print(4 != 4)
print(4 > 4)
print(4 >= 4)
'''
True
False
False
True
'''
조건문 / for문 / while
# 조건문
x = 3
if x == 3:
print("true1") # true1
if x == 3:
print("true2") # true2 상관 없음
x = 3
if x == 3:
print("true1")
elif x == 3:
print("true2") # 대전제가 if, elif는 위의 if가 틀려야 실행됨 따라서 실행X
else:
print("x!=3") # 대전제가 if, if와 elif가 둘다 틀려야 실행됨
# for문
sum = 0
for i in range(11):
sum = sum + i # i는 0부터 11까지(010)
print("i:", i) # i: 10
print("sum:", sum) # sum: 55
sum2 = 0
for j in range(1, 11, 2): # j 1~11까지 2씩 증가하면서 5회 반복
sum2 = sum2 + j
print("j:", j) # j: 9
print("sum:", sum) # sum: 55
# while
sum = 0
i = 1
while i < 11: # i가 11보다 작을 때까지만 아래 코드를 실행
sum = sum+i
print("i:", i)
i = i+1
print("sum:", sum)
while의 특징 : 특정 조건 실행 가능
# while
sum = 0
i = 1
while i < 11: # i가 11보다 작을 때까지만 아래 코드를 실행
sum = sum+i
print("i:", i)
if( i == 5 ) : break # 특정 조건을 걸어 break 실행 가능
i = i+1
print("sum:", sum)
함수
def sum(math, eng):
return (math + eng)
print("sum:", sum(30, 40)) # sum: 70
* 파이썬 기본 제공 함수도 있고(ex. time()) 개발자가 직접 만들어 사용할 수도 있음
라즈베리파이3 핀맵
물리적 핀번호와 GPIO 핀번호가 다르다. 참고
물리적 핀번호
GPIO 핀번호 : 소프트웨어에서 입력 또는 출력핀으로 지정될 수 있다
led 연결
import RPi.GPIO as GPIO # RPi.GPIO 모듈을 GPIO 라는 이름으로 불러옴
led_pin = 17 # 17 : BCM GPIO 핀 번호
GPIO.setmode(GPIO.BCM)
# GPIO.setmode 함수를 호출하여 BCM GPIO 핀 번호 사용하도록 설정
GPIO.setup(led_pin, GPIO.OUT)
# GPIO.setup 함수를 호출해 led_pin을 GPIO 출력으로 설정 => True 또는 False를 써 연결된 LED 조작 가능
GPIO.output(led_pin, True)
# GPIO.output 함수를 호출해 led_pin을 True로 설정 => led_pin에 연결된 LED 켜짐
try:
while True: # 빈 while문을 수행하며 LED가 켜진 상태 유지
pass
except KeyboardInterrupt: # ctrl+c를 누르면 키보드 인터럽트 처리
pass
GPIO.cleanup() # GPIO 핀의 상태 초기화
결과
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) # led 켜짐
time.sleep(0.5) # 0.5초간 지연
GPIO.output(led_pin, False) # led 꺼짐
time.sleep(0.5) # 0.5초간 지연
except KeyboardInterrupt:
pass
GPIO.cleanup()
# 1초 주기로 led가 켜졌다 꺼졌다 함 => 1Hz의 주파수
LED 제어
PWD 제어
전기 펄스의 주파수와 폭을 조절하는 것을 PWM 출력 제어라고 함
주파수 : 1초동안 반복되는 사이클의 개수, 단위는 Hz
1Hz : 1초에 1회
100Hz : 1초에 100회
PWM 클래스
sleep을 안걸어줘도 됨
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
# 첫번째 인자 : 핀 번호, 두번째 인자 : 주파수 값
pwm.start(50.0) # 0.0~100.0
# start함수 호출, 파형 내보내기 시작 / 사각파형의 HIGH 구간의 비율을 나타냄
try:
while True: # led 핀으로 나가는 PWM 파형 유지
pass
except KeyboardInterrupt:
pass
pwm.stop() # pwm 객체에 대해 stop 함수 호출(PWM 파형 출력 멈춤)
GPIO.cleanup()
# 1초 주기로 점멸
부저
떴다떴다 비행기 연주
import RPi.GPIO as GPIO
import time
buzzer_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer_pin, GPIO.OUT)
pwm = GPIO.PWM(buzzer_pin, 1.0)
pwm.start(50.0)
melody = [330,294,262,294,330,330,330,294,294,294,330,330,330,330,294,262,294,330,330,330,294,294,330,294,262]
# melody = [262,294,330,349,392,440,494,523]
# 음에 해당하는 주파수
for note in range(0, 25): # note 변수 값을 0부터 25 미만의 정수에 대해 아래 두줄을 수행
pwm.ChangeFrequency(melody[note]) # pwm 객체에 대해 ChangeFrequency 함수를 호출해 melody[note] 주파수로 설정
time.sleep(0.5)
pwm.ChangeDutyCycle(0.0) # pwm 객체에 대해 ChangeDutyCycle 함수를 호출해 사각 파형의 HIGH 구간을 0.0%로 설정 => 부저음 안남
pwm.stop()
GPIO.cleanup()
서브모터
import RPi.GPIO as GPIO
import time
servo_pin = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
# pwm.stop() # 강제로 멈추기
pwm = GPIO.PWM(servo_pin, 50) # 50Hz
pwm.start(3.0) #0.6ms
# time.sleep(2.0)
# pwm.ChangeDutyCycle(0.0)
# for cnt in range(0, 3):
# pwm.ChangeDutyCycle(3.0)
# time.sleep(1.0)
# pwm.ChangeDutyCycle(12.5)
# time.sleep(1.0)
for t_high in range(30, 125):
pwm.ChangeDutyCycle(t_high/10.0)
time.sleep(0.02)
pwm.ChangeDutyCycle(3.0)
time.sleep(1.0)
pwm.ChangeDutyCycle(0.0)
pwm.stop()
GPIO.cleanup()
아주 미세하게 톱니 바퀴가 돈다...
input
사용자 입력을 받는 함수
버튼
# 버튼 입력 콘솔창 확인
import RPi.GPIO as GPIO
button_pin = 27
GPIO.setmode(GPIO.BCM)
GPIO.setup(button_pin, GPIO.IN)
try:
while True:
buttonInput = GPIO.input(button_pin)
print(buttonInput)
except KeyboardInterrupt:
pass
GPIO.cleanup()
버튼과 led 연결
# 버튼 값에 따라 LED 켜기
import RPi.GPIO as GPIO
button_pin = 27
led_pin = 22
GPIO.setmode(GPIO.BCM)
GPIO.setup(button_pin, GPIO.IN)
GPIO.setup(led_pin, GPIO.OUT)
try:
while True:
buttonInput = GPIO.input(button_pin)
GPIO.output(led_pin, buttonInput)
except KeyboardInterrupt:
pass
GPIO.cleanup()
# 버튼 누르면 켜지고 다시 누르면 꺼지게 하기
import RPi.GPIO as GPIO
button_pin = 27
led_pin = 22
GPIO.setmode(GPIO.BCM)
GPIO.setup(button_pin, GPIO.IN)
GPIO.setup(led_pin, GPIO.OUT)
buttonInputPrev = False
ledOn = False
try:
while True:
buttonInput = GPIO.input(button_pin)
if buttonInput and not buttonInputPrev:
print("rising edge")
ledOn = True if not ledOn else False
# ledOn이 true면 false로 하고 false면 true로 한다
GPIO.output(led_pin, ledOn)
elif not buttonInput and buttonInputPrev:
print("falling edge")
else:
pass
buttonInputPrev = buttonInput
except KeyboardInterrupt:
pass
GPIO.cleanup()
버튼 인터럽트로 LED 켜기
GPIO.add event callback
인터럽트 : 프로그램 실행 중 CPU의 현재 처리 순서를 중단시키고 다른 동작을 수행하도록 요구하는 시스템 동작
# 버튼 인터럽트로 LED 켜기
import RPi.GPIO as GPIO
led_state = False
led_state_changed = False
def buttonPressed(channel): # 이벤트 발생 시 처리 함수
global led_state # led_state 전역 변수 선언
global led_state_changed # led_state_change 전역 변수 선언
led_state = True if not led_state else False # led state가 true면 false로 바꾸고, false면 true로 바꿈
led_state_changed = True # 함수 처리 후 led_state_changed 변수 True로 처리
button_pin = 27
led_pin = 22
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)
GPIO.setup(button_pin, GPIO.IN)
GPIO.add_event_detect(button_pin, GPIO.RISING) # event 감지하는 방법 : GPIO 핀이 low에서 high로 올라갈 때 감지
GPIO.add_event_callback(button_pin, buttonPressed) # event 감지 후 불러올 함수 선언 callback
try:
while True:
if led_state_changed == True: # led_state_changed가 True면 False로 다시 돌려놓음
led_state_changed = False
GPIO.output(led_pin, led_state)
except KeyboardInterrupt:
pass
GPIO.cleanup()
* 백업을 잊지 말자 : 우클-download
쓰레드 Thread
프로세스 : 실행중인 프로그램
쓰레드 : 프로세스 내에서 실행되는 작은 작업의 단위
쓰레드의 동기화 이슈 : 여러 스레드가 동일한 자원(데이터)에 접근 시 동기화 이슈 발생
=> 동일 자원을 여러 스레드가 동시 수정 시, 각 스레드의 결과에 영향을 줌
==> Lock 처리 필요 설명 링크 참고
* 쓰레드와 락은 면접 시에도 많이 물어보는 중요한 항목인만큼 개념 정리를 잘 하자!
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()
느낀 점
복습할 사항 : vi, nano 에디터 연습
쓰레드, 락 개념 이해 쓰레드
손으로 조작하며(전선 연결하고 저항 꽂고)하니까 재밌다!
바로바로 실행도 되니까 더 재밌다!
'공부 > [TIL] Digital Twin Bootcamp' 카테고리의 다른 글
TIL_220111_IOT (0) | 2022.01.11 |
---|---|
TIL_220110_IOT (0) | 2022.01.11 |
TIL_220106_Backend (0) | 2022.01.06 |
TIL_210105_Backend (0) | 2022.01.05 |
TIL_220104_Vision 인식 (1) | 2022.01.04 |