Python을 이용한 원격 제어(Remote control) Coding 예
필요한 배경 지식
Web page Checkbox와 Button를 이용하여 Server 측의 LED(Server 측)를 제어하는 프로그램 예
실험을 위한 준비
실험 방법
Web page Drop-down list(select)를 이용한 제어 예
실험 방법
Python 언어를 이용한 프로그램을 이해 하는데 도움이 되는 기본 프로그램 예
- 필요한 배경 지식
- Web page Checkbox를 이용하여 Server 측의 LED(Server 측를 제어하는 프로그램 예
- Web page Drop-down list(select)를 이용한 제어 예
- HTML: Web pages 작성에 필요한 Markup language
- JavaScript: Web pages 작성에 필요한 Programming language
- Python: HTML과 Web의 Programming language
- Linux OS: Raspberry Pi의 OS 가 Linux 이다.
- 필요한 소프트웨어 Tool: Flask, gpiozero
- Flask 설치하기: Python를 이용한 Webserver 환경 만들기를 참고 할 것.
- gpiozero 설치 하기를 참고 할 것.
- 프로그램 예: web-led-control.zip
- Server 측의 프로그램 예: web-led-control.py
- Client 측의 프로그램 예: web-led-control.htm
- 학습 포인트
- GET, POST Method를 사용한 Client와 Server 사이의 Data 송수신(JSON format)에 대한 이해
- Form data(Checkbox)를 JSON format으로 Server에 전송하기.
- Server 측 GPIO Pin의 상태를 Arry data로 변환하여 JSON format으로 전송하기.
- HTML 문서에서 버튼을 이용한 JavaScript 함수 실행 하기.
- JSON format으로 전송된 Data의 내용을 Web page에 표시 하기.
- 불규칙한 번호로 배열된 GPIO Pin를 Array로 처리 하기
Raspberry Pi 3와 Python web server(Flask 사용)를 사용한 원격제어 제어 시스템의 구성은 아래와 같다.
LED 제어 Web Page 예
web-led-control.py 프로그램
#!/user/bin/env python3
# coding=utf8
from flask import Flask, render_template, request
from gpiozero import LEDBoard
app = Flask(__name__)
import json
import time, threading
from datetime import datetime
leds = LEDBoard(9, 25, 11, 8, 7, 5, 6, 12)
# ledList[ ]: LED의 상태를 저장 히기 위한 Array
# 1, 3번이 Turn on 된 경우: [0,1,0,1,0,0,0,0] 와 같은 값을 갖는다.
ledList = [0,0,0,0,0,0,0,0]
ledsLen = len(ledList)
# 주기적인 제어(Shift, Blinking) Mode
# 0: 정지, 1: leftRotation, 2: rightRotation, 3: Blinking
operationMode = 0
# 이 함수는 0.5Sec 주기로 실행 된다.
def periodControl():
global operationMode
if operationMode == 1:
leftRotation()
if operationMode == 2:
rightRotation()
if operationMode == 3:
leds.toggle()
threading.Timer(0.5, periodControl).start()
# 일정 주기로 실행되는 periodControl() 함수를 시작 한다.
periodControl()
# LED의 한 Bit를 Left rotation 시킨다.
def leftRotation():
temp = leds[ledsLen - 1].value
for i in range(ledsLen - 1, 0, -1):
if leds[i-1].value == 1:
leds[i].on()
else:
leds[i].off()
if temp == 1:
leds[0].on()
else:
leds[0].off()
# LED의 한 Bit를 Right rotation 시킨다.
def rightRotation():
temp = leds[0].value
for i in range(0, ledsLen - 1):
if leds[i+1].value == 1:
leds[i].on()
else:
leds[i].off()
if temp == 1:
leds[ledsLen - 1].on()
else:
leds[ledsLen - 1].off()
# Web browser에서 이 Server의 / 에 접속하면 web-led-control.htm
# 페이지를 Web browser에 전송 한다.
# (예: http://Raspberry Pi의 IP 주소:2880/)
# 2880은 공유기에서 포트포워드 설정한 포트 번호 임.
@app.route('/')
def checkBoxLED():
return render_template('web-led-control.htm')
@app.route('/checkBoxLEDControl', methods=['POST'])
def LEDControl():
global operationMode
# Checkbox의 Check list(HTML File에서 Value로 정의 됨)를 갖어 온다.
checkbox = request.form.getlist('check')
print('checkbox: ',checkbox)
# 주기적인 제어(Shift, Blinking)를 정지 한다.
operationMode = 0
# LED를 모두 Turn off 한다.
leds.off()
# Checkbox에 수신된 문자열 List의 내용과 일치 하는 led를 Turn on 한다.
for ledNo in checkbox:
i = int(ledNo)
leds[i].on()
return ('Y');
@app.route('/checkBoxLEDGet', methods=['GET'])
def LEDGet():
# GET Data를 갖어 온다. 이 예에서는 이 Data를 사용하지는 않는다.
getMsg = request.args.get('getLED')
#print('getMsg: ',getMsg)
# LED의 상태를 Json format으로 Web page에 Return 하기 위하여
# ledList[]에 저장 한다.
for i in range(0, ledsLen):
ledList[i] = leds[i].value
# LED의 상태를 확인 한다.
print('ledList: ',ledList)
return json.dumps({'status':'OK','checkbox':ledList});
# LED left shift
@app.route('/ledLeftShift', methods=['GET'])
def leftShit():
# GET Data를 갖어 온다. 이 예에서는 이 Data를 사용하지는 않는다.
getMsg = request.args.get('leftShift')
#print('getMsg: ',getMsg)
global operationMode
leds.off()
leds[0].on()
operationMode = 1
return ('Y');
# LED right shift
@app.route('/ledRightShift', methods=['GET'])
def rightShift():
# GET Data를 갖어 온다. 이 예에서는 이 Data를 사용하지는 않는다.
getMsg = request.args.get('rigthShift')
#print('getMsg: ',getMsg)
global operationMode
leds.off()
leds[ledsLen - 1].on()
operationMode = 2
return ('Y');
# LED blinking
@app.route('/ledBlinking', methods=['GET'])
def blinking():
# GET Data를 갖어 온다. 이 예에서는 이 Data를 사용하지는 않는다.
getMsg = request.args.get('blinking')
#print('getMsg: ',getMsg)
global operationMode
leds.off()
operationMode = 3
return ('Y');
# LED Stop
@app.route('/ledClear', methods=['GET'])
def clear():
# GET Data를 갖어 온다. 이 예에서는 이 Data를 사용하지는 않는다.
getMsg = request.args.get('clear')
#print('getMsg: ',getMsg)
global operationMode
leds.off()
operationMode = 0
return ('Y');
if __name__ == '__main__':
app.run(host='0.0.0.0', port=2880, debug=True)
# app.run(host='0.0.0.0', port=2880, debug=False)
- Raspberry Pi의 GPIO 상태를 보기 위한 LED Arary 회로 만들기
- Raspberry Pi의 GPIO 출력을 LED로 확인 할 수 있는 회로와 제작된 LED Arary 모듈 예
- Raspberry Pi의 GPIO Pin과 LED Pin 연결하기
- LED Pin 1번: Header Pin 21번 GPIO 09번
- LED Pin 2번: Header Pin 22번 GPIO 25번
- LED Pin 3번: Header Pin 23번 GPIO 11번
- LED Pin 4번: Header Pin 24번 GPIO 08번
- LED Pin 5번: Header Pin 26번 GPIO 07번
- LED Pin 6번: Header Pin 29번 GPIO 05번
- LED Pin 7번: Header Pin 31번 GPIO 06번
- LED Pin 8번: Header Pin 32번 GPIO 12번
아래 회로를 참고하여 LED Arary 모듈을 만든다.
LED Arary 회로 예 |
제작된 LED Arary 모듈 |
Raspberry Pi GPIO Header의 Pin 배치도를 참고하여 아래와 같이 Raspberry Pi GPIO Header Pin과 LED Arary 모듈을 연결 한다.
- 필요한 소프트웨어 Tool을 설치 한다.
- 적당한 폴더(예:webapp)에 Server 측 프로그램(web-led-control.py)을 복사하여 web-led-control.py File을 만든다.
- web-led-control.py 가 있는 폴더에 templates 폴더를 만들고, web-led-control.htm을 복사 한다.
- Putty로 Raspberry Pi에 Login 하고, web-led-control.py가 있는 폴더로 이동 한다.
- 다음 명령으로 web-led-control.py를 실행 한다.
- Chrome browser를 실행하고 아래 예를 참고하여 Web server에 연결 하면 web-led-control.htm 페이지가 Load 된다.
- 임의의 Checkbox를 Check하고 "LED On/Off Control" 버튼을 클릭 하면, Web page에서 Check된 Checkbox와 대응하는 위치의 LED 가 Turn on 된다.
- Web page에 있는 제어 버튼을 클릭 한 다음, 실험 보오드에서 LED 상태와 Checkbox를 확인 한다.
python3 web-led-control.py
http://Raspberry Pi의 IP 주소:2880/
2880은 공유기에서 포트포워드로 설정한 포트 번호 이다.
- 프로그램 예: web-led-select-control.zip
- Server 측의 프로그램 예: web-led-select-control.py
- Client 측의 프로그램 예: web-led-select-control.htm
- 학습 포인트
- Drop-down list를 이용한 제어
- Drop-down list에서 선택된 명령을 Server에서 실행 하고,
- 현재 Server 측의 상태를 Checkbox에 표시하기.
윗 예에서 명령 버튼을 Drop-down list로 변경하여 Drop-down list 응용 능력을 키우기 위한 예 이다.
필요한 소프트웨어 Tool, 실험을 위한 준비는 윗 예를 참고 할 것.
Drop-down list를 이용하여 LED를 제어하는 Web Page 예
web-led-select-control.py 프로그램
#!/user/bin/env python3
# coding=utf8
from flask import Flask, render_template, request
from gpiozero import LEDBoard
app = Flask(__name__)
import json
import time, threading
from datetime import datetime
leds = LEDBoard(9, 25, 11, 8, 7, 5, 6, 12)
# ledList[ ]: LED의 상태를 저장 히기 위한 Array
# 1, 3번이 Turn on 된 경우: [0,1,0,1,0,0,0,0] 와 같은 값을 갖는다.
ledList = [0,0,0,0,0,0,0,0]
ledsLen = len(ledList)
# 주기적인 제어(Shift left, Shift right, Blinking) Mode
# 0: 정지, 1: LeftRotation, 2: RightRotation, 3: Blinking
operationMode = 0
# 이 함수는 0.5Sec 주기로 실행 된다.
def periodControl():
global operationMode
if operationMode == 1:
leftRotation()
if operationMode == 2:
rightRotation()
if operationMode == 3:
leds.toggle()
threading.Timer(0.5, periodControl).start()
# 일정 주기로 실행되는 periodControl() 함수를 시작 한다.
periodControl()
# LED의 한 Bit를 Left rotation 시킨다.
def leftRotation():
temp = leds[ledsLen - 1].value
for i in range(ledsLen - 1, 0, -1):
if leds[i-1].value == 1:
leds[i].on()
else:
leds[i].off()
if temp == 1:
leds[0].on()
else:
leds[0].off()
# LED의 한 Bit를 Right rotation 시킨다.
def rightRotation():
temp = leds[0].value
for i in range(0, ledsLen - 1):
if leds[i+1].value == 1:
leds[i].on()
else:
leds[i].off()
if temp == 1:
leds[ledsLen - 1].on()
else:
leds[ledsLen - 1].off()
# Web browser에서 이 Server의 / 에 접속하면 web-led-select-control.htm
# 페이지를 Web browser에 전송 한다.
# (예: http://Raspberry Pi의 IP 주소:2880/)
# 2880은 공유기에서 포트포워드 설정한 포트 번호 임.
@app.route('/')
def checkBoxLED():
return render_template('web-led-select-control.htm')
@app.route('/selectLEDControl', methods=['POST'])
def LEDControl():
global operationMode
# Checkbox의 Check list(Check 상태로 HTML File에서 Value로 정의 됨)를 갖어 온다.
checkbox = request.form.getlist('check')
print('checkbox: ',checkbox)
selCommand = request.form.get('selectCommand')
print('selCommand: ',selCommand)
# 주기적인 제어(Shift, Blinking)를 정지 한다.
operationMode = 0
# Set LED
if selCommand == '1':
# LED를 모두 Turn off 한다.
leds.off()
# Checkbox에 수신된 문자열 List의 내용과 일치 하는 led를 Turn on 한다.
for ledNo in checkbox:
i = int(ledNo)
leds[i].on()
print('LED')
return json.dumps({'command':'1','status':'Y'})
# Get LED status
if selCommand == '2':
# LED의 상태를 Json format으로 Web page에 Return 하기 위하여
# ledList[]에 저장 한다.
for i in range(0, ledsLen):
ledList[i] = leds[i].value
# LED의 상태를 확인 한다.
print('ledList: ',ledList)
return json.dumps({'command':'2','status':'Y','checkbox':ledList})
# LED left shift
if selCommand == '3':
leds.off()
leds[0].on()
operationMode = 1
return json.dumps({'command':'3','status':'Y'});
# LED right shift
if selCommand == '4':
leds.off()
leds[ledsLen - 1].on()
operationMode = 2
return json.dumps({'command':'4','status':'Y'});
# LED blinking
if selCommand == '5':
leds.off()
operationMode = 3
return json.dumps({'command':'5','status':'Y'});
# LED Clear
if selCommand == '6':
leds.off()
operationMode = 0
return json.dumps({'command':'6','status':'Y'});
if __name__ == '__main__':
app.run(host='0.0.0.0', port=2880, debug=True)
# app.run(host='0.0.0.0', port=2880, debug=False)
- 적당한 폴더에 Server 측 프로그램(web-led-select-control.py)을 복사하여 web-led-select-control.py File을 만든다.
- web-led-control.py 가 있는 폴더(예: webapp)에 templates 폴더를 만들고, web-led-select-control.htm을 복사 한다.
- Putty로 Raspberry Pi에 Login 하고, web-led-select-control.py가 있는 폴더로 이동 한다.
- 다음 명령으로 web-led-select-control.py를 실행 한다.
- Chrome browser를 실행하고 아래 예를 참고하여 Web server에 연결 하면 web-led-select-control.htm 페이지가 Load 된다.
- 임의의 Checkbox를 Check하고 Drop-down list에서 "Turn on/off"를 선택하고 "LED Control" 버튼을 클릭하면 , Web page에서 Check된 Checkbox와 대응하는 위치의 LED 가 Turn on 된다.
- Drop-down list에서 다른 명령도 선택하여 실행 시키고, 실험 보오드에서 LED 상태와 Checkbox를 확인 한다.
python3 web-led-select-control.py
http://Raspberry Pi의 IP 주소:2880/
2880은 공유기에서 포트포워드로 설정한 포트 번호 이다.