RC Car키트를 조립한 뒤 기본 코드를 작성했다. 원래 QT로 만든 UI에서 커맨드를 입력받아 명령을 수행하는 코드를 짰었는데, 여러가지 센서를 사용해보면 좋을 것 같아서 UI 를 과감히 제거(!)하고 "에어 컨트롤러"를 만들기로 했다.
오늘은 RC Car 프로젝트에서 라즈베리 파이와 관련된 기본적인 내용을 정리한다.
Motor HAT에 DC 모터와 Servo 모터를 연결한다. DC모터는 뒷바퀴에 연결해서 앞뒤로 차량이 오고 갈 수 있게 하고, Servo 모터는 앞바퀴에 연결해서 좌회전, 우회전이 가능하도록 한다.
라즈베리파이에서 I2C 통신을 사용하기 위해 설정해준다.
# raspi-config 설정
sudo apt-get update
sudo raspi-config
# 3. Interface Options 선택
# I5 I2C 를 Enable 로 설정
# raspi-config 를 닫고
# I2C 유틸리티 설치
sudo apt-get install python3-smbus i2c-tools
# 연결된 I2C 디바이스를 검색하면
sudo i2cdetect -y 1
# 모터햇의 i2c 주소를 알 수 있다.
DC 모터와 Servo 모터의 테스트가 가능한 코드가 포함되어 있다.
wget http://wiki.geekworm.com/images/a/ac/Raspi-MotorHAT-python3.zip
라즈베리파이 자체를 브로커 서버로 사용할 경우 MQTT로 통신하기 위해 개발 환경을 설정한다.
# mqtt 설치
sudo apt install mosquitto -y
# 프로세스 확인 명령어로 확인하면, 설치하자마자 중계기가 실행중임을 알 수 있다
ps -ef | grep mosquitto
# borker server test 를 위해 app을 설치해서 테스트 해본다
sudo apt install mosquitto-clients –y
# 터미널 두 개로 확인
# mosquitto_sub –t “ondol”
# mosquitto_pub –t “ondol” –m “HI”
# => 잘 나오면 설치 성공
# 인바운드 규칙 설정
sudo vi /etc/mosquitto/mosquitto.conf
# 파일 가장 아래에 다음 내용을 추가하고 저장한다
port 1883
allow_anonymous true
# config 설정대로 MQTT broker 서버를 재실행한다
cd /etc/mosquitto
sudo /etc/init.d/mosquitto stop
sudo mosquitto –c mosquitto.conf –v
파이썬에서 mqtt를 사용하기 위해 관련 라이브러리를 설치한다.
sudo pip3 install paho-mqtt
cmd_thread.py
from Raspi_MotorHAT import Raspi_MotorHAT, Raspi_DCMotor
from Raspi_PWM_Servo_Driver import PWM
import threading
import paho.mqtt.client as mqtt
import socket
class CmdThread(threading.Thread):
BROKER_ADDRESS = socket.gethostbyname(socket.gethostname())
speed_idx = 0
speed = [100, 150, 200, 255]
front_or_back = "" # 현재 직진 중인가? 후진 중인가?
def __init__(self):
super().__init__()
self.client = mqtt.Client("cmd_sub")
self.client.connect(self.BROKER_ADDRESS)
self.client.subscribe("command")
self.client.on_message = self.on_command
self.mh = Raspi_MotorHAT(addr=0x6f)
self.myMotor = self.mh.getMotor(2)
self.pwm = PWM(0x6f)
self.pwm.setPWMFreq(60)
def on_command(self, client, userdata, message):
cmd = str(message.payload.decode("utf-8"))
if "go" == cmd:
self.front_or_back = "front"
self.go()
elif "back" == cmd:
self.front_or_back = "back"
self.back()
elif "stop" == cmd:
self.front_or_back = ""
self.stop()
elif "left_max" == cmd:
self.left_max()
elif "left_min" == cmd:
self.left_min()
elif "right_max" == cmd:
self.right_max()
elif "right_min" == cmd:
self.right_min()
elif "mid" == cmd:
self.mid()
elif "speed" in cmd:
idx = int(cmd.split("=")[1])
if idx <= 2:
self.speed_idx = 0
elif idx <= 4:
self.speed_idx = 1
elif idx <= 6:
self.speed_idx = 2
else:
self.speed_idx = 3
self.speed_changed()
def speed_changed(self):
if self.front_or_back == "front":
self.go()
elif self.front_or_back == "back":
self.back()
def run(self):
self.client.loop_forever()
def go(self):
self.myMotor.setSpeed(self.speed[self.speed_idx])
self.myMotor.run(Raspi_MotorHAT.BACKWARD)
def back(self):
self.myMotor.setSpeed(self.speed[self.speed_idx])
self.myMotor.run(Raspi_MotorHAT.FORWARD)
def stop(self):
self.myMotor.setSpeed(self.speed[self.speed_idx])
self.myMotor.run(Raspi_MotorHAT.RELEASE)
def left_max(self):
self.pwm.setPWM(0, 0, 300)
def left_min(self):
self.pwm.setPWM(0, 0, 340)
def mid(self):
self.pwm.setPWM(0, 0, 375)
def right_max(self):
self.pwm.setPWM(0, 0, 450)
def right_min(self):
self.pwm.setPWM(0, 0, 410)
main app.py
import cmd_thread
if __name__ == '__main__':
cmd_th = cmd_thread.CmdThread()
cmd_th.start()
그럼 이제 ESP32에 MQTT 통신을 하는 펌웨어를 만들어 자동차를 조종해보자