Flask๋ฅผ ์ด์ฉํ์ฌ ์ธ๋ถ์์ DC๋ชจํฐ ์ ์ดํ๊ธฐ with Android
๐ก ์ด๊ธฐ ์ค์ (OS ์ค์น, ์ค์ ๋ฑ)์ ๋์ด ์๋ค๋ ๊ฐ์ ํ์ ์์ฑํ์์ต๋๋ค.
์ค๋น๋ฌผ
- ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด3 B+
- DC๋ชจํฐ (ํน์ ๊ธฐํ ์ผ์ ๋ฑ)
- Android Studio
- (์ ํ) ํ ์คํธ ๊ธฐ๊ธฐ
Flask ์ค์น
pi@raspberrypi:~ $ sudo pip install flask
์์ ๋๋ ํ ๋ฆฌ ์์ฑ
pi@raspberrypi:~ $ mkdir workspace
pi@raspberrypi:~ $ cd workspace
๋ชจํฐ ์ ์ด ์ฝ๋ ์์ฑ
vi
๋ช
๋ น์ด๋ฅผ ํตํด ํ์ผ ์์ฑ. ํ์ผ ์ด๋ฆ์ ์ ๋นํ ์ง์ด๋ ๋ฌด๊ดํจ.
pi@raspberrypi:~/workspace $ vi motor.py
motor.py
# -*- coding: utf-8 -*-
# ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด GPIO ํจํค์ง
import RPi.GPIO as GPIO
from time import sleep
# PIN ์
์ถ๋ ฅ ์ค์
OUTPUT = 1
INPUT = 0
# PIN ์ค์
HIGH = 1
LOW = 0
# ์ค์ ํ ์ ์
#PWM PIN
ENA = 26 #37 pin
ENB = 0 #27 pin
#GPIO PIN
IN1 = 19 #37 pin
IN2 = 13 #35 pin
IN3 = 6 #31 pin
IN4 = 5 #29 pin
# ํ ์ค์ ํจ์
def setPinConfig(EN, INA, INB):
GPIO.setup(EN, GPIO.OUT)
GPIO.setup(INA, GPIO.OUT)
GPIO.setup(INB, GPIO.OUT)
# 100khz ๋ก PWM ๋์ ์ํด
pwm = GPIO.PWM(EN, 100)
# ์ฐ์ PWM ๋ฉ์ถค.
pwm.start(0)
return pwm
# ๋ชจํฐ ์ ์ด ํจ์
def setMotorContorl(pwm, INA, INB, speed, stat):
#๋ชจํฐ ์๋ ์ ์ด PWM
pwm.ChangeDutyCycle(speed)
if stat == FORWARD:
GPIO.output(INA, HIGH)
GPIO.output(INB, LOW)
#๋ค๋ก
elif stat == BACKWORD:
GPIO.output(INA, LOW)
GPIO.output(INB, HIGH)
#์ ์ง
elif stat == STOP:
GPIO.output(INA, LOW)
GPIO.output(INB, LOW)
# ๋ชจํฐ ์ ์ดํจ์ ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด ํ๋ฒ๋ ๋ํ(๊ฐ์)
def setMotor(ch, speed, stat):
if ch == CH1:
#pwmA๋ ํ ์ค์ ํ pwm ํธ๋ค์ ๋ฆฌํด ๋ฐ์ ๊ฐ์ด๋ค.
setMotorContorl(pwmA, IN1, IN2, speed, stat)
else:
#pwmB๋ ํ ์ค์ ํ pwm ํธ๋ค์ ๋ฆฌํด ๋ฐ์ ๊ฐ์ด๋ค.
setMotorContorl(pwmB, IN3, IN4, speed, stat)
# GPIO ๋ชจ๋ ์ค์
GPIO.setmode(GPIO.BCM)
#๋ชจํฐ ํ ์ค์
#ํ ์ค์ ํ PWM ํธ๋ค ์ป์ด์ด
pwmA = setPinConfig(ENA, IN1, IN2)
pwmB = setPinConfig(ENB, IN3, IN4)
# ์ข
๋ฃ
GPIO.cleanup()
์ถ์ฒ: https://blog.naver.com/chandong83/221156273595
Flask ์ดํ๋ฆฌ์ผ์ด์ ์์ฑ
vi
๋ช
๋ น์ด๋ฅผ ํตํด ํ์ผ ์์ฑ. ํ์ผ ์ด๋ฆ์ ์ ๋นํ ์ง์ด๋ ๋ฌด๊ดํจ.
pi@raspberrypi:~/workspace $ vi app.py
app.py
from flask import Flask
from time import sleep
import RPi.GPIO as GPIO
import motor
GPIO.setwarnings(False)
# ๋ชจํฐ ์ํ
STOP = 0
FORWARD = 1
BACKWORD = 2
# ๋ชจํฐ ์ฑ๋
CH1 = 0
CH2 = 1
app = Flask(__name__)
# index ํ์ด์ง๋ ๋ชจํฐ์ ์ด์๋ ๊ด๊ณ ์์
@app.route('/')
def index():
return 'Hello World!'
@app.route('/left')
def left():
motor.setMotor(CH1, 100, FORWARD)
# 15์ด ๋๊ธฐ
sleep(15)
motor.setMotor(CH1, 100, STOP)
# return ๊ฐ์ ์๋ฏธ ์์
return 'Sucess!'
@app.route('/right')
def right():
motor.setMotor(CH2, 100, FORWARD)
# 15์ด ๋๊ธฐ
sleep(15)
motor.setMotor(CH2, 100, STOP)
# return ๊ฐ์ ์๋ฏธ ์์
return 'Sucess!'
if __name__ == '__main__':
app.run(host='0.0.0.0')
์ธ๋ถ์์ Flask
์ดํ๋ฆฌ์ผ์ด์
์ ์ ์ํ๋ ค๋ฉด
app.run()
์ ํ๋ผ๋ฏธํฐ๋กhost='0.0.0.0'
๋ฅผ ๋๊ฒจ์ค๋ค.Flask
์ ๊ธฐ๋ณธ ํฌํธ๋5000
์ ์ฌ์ฉํ๋ค. ๊ณต์ ๊ธฐ๋ฅผ ์ฌ์ฉ์ค์ด๋ผ๋ฉด ํฌํธํฌ์๋ฉ ๊ธฐ๋ฅ์ ํตํด5000
ํฌํธ๋ฅผ ์ด์ด์ผ ํ๋ค.
Flask ์ดํ๋ฆฌ์ผ์ด์ ์คํ
pi@raspberrypi:~/workspace $ python3 app.py
๋ง์ฝ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํ์ํค๊ณ ์ถ๋ค๋ฉด &
๋ฅผ ๋ถ์ฌ์ ์คํํ๋ฉด ๋๋ค.
pi@raspberrypi:~/workspace $ python3 app.py &
์ด๋ง์ ๋ ๊ท์ฐฎ๊ณ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด๊ฐ ๋ถํ ์ด ๋ ๋๋ง๋ค ์๋์ผ๋ก ์คํ์ํค๊ณ ์ถ๋ค๋ฉด
pi@raspberrypi:~/workspace $ sudo vi /etc/rc.local
rc.local
...(์๋ต)...
# exit 0 ๋ฐ๋ก ์ ์ค์ ์์ฑํด์ผ ํจ!
# ๊ถํ์ด ํ์์๋ ์ฝ๋์ง๋ง ํน์ ๋ชจ๋ฅผ ์ผ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ ์์
sudo pyhon3 /home/pi/workspace/app.py &
exit 0
์ฌ๊ธฐ์ ์ฃผ์ํด์ผํ ์ ์ app.py
ํ์ผ์ด ์๋ ๊ฒฝ๋ก๊น์ง ์ ๋๊ฒฝ๋ก๋ก ์์ฑํด์ผํ๋ค.
์ ์ฅ ํ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด๋ฅผ reboot
ํ๋ฉด ์์์ ๋ง๋ Flask
์ดํ๋ฆฌ์ผ์ด์
์ด ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํ๋๋ค. ํ์ธํ๊ณ ์ถ๋ค๋ฉด ๋ค์์ ๋ช
๋ น์ด๋ฅผ ํตํด ํ๋ก์ธ์ค๊ฐ ์๋ํ๊ณ ์๋ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
pi@raspberrypi:~ $ top | grep 'python'
์ดํ๋ฆฌ์ผ์ด์ ์ ์ฃฝ์ด๊ณ ์ถ๋ค๋ฉด ์์ ๋ช ๋ น์ด๋ฅผ ํตํด PID๋ฅผ ์์๋ธ ํ ๋ค์๊ณผ ๊ฐ์ด ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ๋๋ค.
pi@raspberrypi:~ $ kill -9 PID
- PID ๋ ์ซ์ ๊ฐ.
์ด์ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ดIP:5000/left
ํน์ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ดIP:5000/right
๋ก ์ ์ํ๋ฉด DC ๋ชจํฐ๊ฐ 15์ด ๋์ ๋์๊ฐ๋ค.
์๋๋ก์ด๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์
in Android Studio
-
์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค.
-
Empty Activity๋ฅผ ์ ํํ๋ค.
-
activity_main.xml
์Button
์ ์ถ๊ฐํ๋ค.<Button android:id="@+id/leftBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="์ผ์ชฝ ๋ชจํฐ" />
-
์๋๋ก์ด๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ํตํด ์ธํฐ๋ท์ ์ ์ํ๋ ค๋ฉด
Manifest
ํ์ผ์์ ๊ถํ์ ์์ฒญํด์ผ ํ๋ค.Manifest
ํ์ผ์ ์ด์ด ๋ค์์ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค.<uses-permission android:name="android.permission.INTERNET" />
-
Volley
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํดbuild.gradle
์ ์ถ๊ฐํ๋ค.dependencies { implementation 'com.android.volley:volley:1.1.1' }
-
MainActivity.java
์ ๋ค์์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.package com.example.test; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.Button; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; public class MainActivity extends AppCompatActivity { private static final int LEFT_TAG = 567; Button leftBtn; RequestQueue queue; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); leftBtn = findViewById(R.id.leftBtn); queue = Volley.newRequestQueue(this); leftBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { leftBtn.setEnabled(false); sendRequest(LEFT_TAG); new Handler().postDelayed(new Runnable() { @Override public void run() { leftBtn.setEnabled(true); } }, 15000); } }); } private void sendRequest(int TAG) { StringRequest stringRequest; switch (TAG) { case LEFT_TAG: stringRequest = new StringRequest(Request.Method.GET, "http://๋ผ์ฆ๋ฒ ๋ฆฌํ์ดIP:5000/left", new Response.Listener<String>() { @Override public void onResponse(String response) { } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); queue.add(stringRequest); break; default: break; } } }
-
์๋ ์ ๋ ธ์ ์ผ๋ก ์์ฑํ๋ ๋ฌธ์๋ฅผ ๋ธ๋ก๊ทธ๋ก ์ฎ๊น.
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote