ラズパイにて、ラジコンカーを自作する－その２


# はじめに

ラズベリーパイにて、自作のラジコンカーをつくったので紹介します。
今回は、制御になります。


![output_7853_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559938/aada34fb-3bbf-763b-b338-539bfe54a85b.gif)

## ラジコンカー関連の記事
- [ラズパイにて、ラジコンカーを自作する－その１](https://qiita.com/kotaproj/items/11d72758b9b21e453216)
- ラズパイにて、ラジコンカーを自作する－その２　←　本記事
- [ラズパイにて、ラジコンカーを自作する－その３](https://qiita.com/kotaproj/items/0a4c919aa8883632f3d4)

# 紹介する内容

- ラズパイ側のラジコン制御


# 作るものの全体

![rajikon-qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559938/19da0dde-175a-4917-aa66-3bda60c95d60.png)

ラズパイ側のプログラムです。


# 作業環境

- ラズベリーパイ3
    - Raspbian Buster with desktop and recommended software
        - Version:February 2020
        - Release date:2020-02-13
        - Kernel version:4.19
        - Python3.7


# 作業手順

今回は、Pythonで実装します。
まずは、モータードライバのクラスを作ります。

## モータードライバの制御

コードは、[ラズパイで動くモノを作る](https://note.com/takasi7/n/ncfc48ab9b851)を参考にさせていただきました。（ほぼ同じ）

コード : ta7291p.py

```
import RPi.GPIO as GPIO

STATE_STOP = 0
STATE_ON = 1

class Motor:
    
    def __init__(self, pina, pinb, pwmpin):
        self.state = STATE_STOP
        self.pina = pina
        self.pinb = pinb
        self.pwmpin = pwmpin
        self.duty = 0

        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)
        
        GPIO.setup(self.pina, GPIO.OUT)
        GPIO.output(self.pina, GPIO.LOW)
        
        GPIO.setup(self.pinb, GPIO.OUT)
        GPIO.output(self.pinb, GPIO.LOW)
        
        GPIO.setup(self.pwmpin, GPIO.OUT)
        GPIO.output(self.pwmpin, GPIO.LOW)
        
        self.pwm = GPIO.PWM(self.pwmpin, 80)
        return

    def setspeed(self,duty):
        self.duty = duty
        if self.state == STATE_ON:
            self.pwm.ChangeDutyCycle(self.duty)
        return self.state

    def accelon(self,back = False):
        if back == False:
            GPIO.output(self.pina, GPIO.HIGH)
            GPIO.output(self.pinb, GPIO.LOW)
        else:
            GPIO.output(self.pina, GPIO.LOW)
            GPIO.output(self.pinb, GPIO.HIGH)

        if self.state == STATE_STOP:
            self.pwm.start(self.duty)

        self.state = STATE_ON
        return self.state
    
    def acceloff(self):
        GPIO.output(self.pina, GPIO.LOW)
        GPIO.output(self.pinb, GPIO.LOW)
        self.pwm.stop()
        self.state = STATE_STOP
        return self.state
    
    def brakeon(self):
        GPIO.output(self.pina, GPIO.HIGH)
        GPIO.output(self.pinb, GPIO.HIGH)
        self.pwm.stop()
        GPIO.output(self.pina, GPIO.LOW)
        GPIO.output(self.pinb, GPIO.LOW)
        self.state = STATE_STOP
        return self.state
```

"GPIO.setwarnings(False)"は、WARNINGを非表示



## ラジコンカーの制御

ラジコンカー部分の制御は以下となります。

コード : picar.py

```
from ta7291p import Motor
import time

FRONT_LEFT_WHEEL_PIN_A = 17
FRONT_LEFT_WHEEL_PIN_B = 4
FRONT_LEFT_WHEEL_PWMPIN = 27

FRONT_RIGHT_WHEEL_PIN_A = 18
FRONT_RIGHT_WHEEL_PIN_B = 23
FRONT_RIGHT_WHEEL_PWMPIN = 24

REAR_LEFT_WHEEL_PIN_A = 6
REAR_LEFT_WHEEL_PIN_B = 13
REAR_LEFT_WHEEL_PWMPIN = 19

REAR_RIGHT_WHEEL_PIN_A = 20
REAR_RIGHT_WHEEL_PIN_B = 12
REAR_RIGHT_WHEEL_PWMPIN = 21

class PiCar():

    def __init__(self):
        self._motors = {}
        self._motors["front_left"] = Motor(FRONT_LEFT_WHEEL_PIN_A, FRONT_LEFT_WHEEL_PIN_B, FRONT_LEFT_WHEEL_PWMPIN)
        self._motors["front_right"] = Motor(FRONT_RIGHT_WHEEL_PIN_A, FRONT_RIGHT_WHEEL_PIN_B, FRONT_RIGHT_WHEEL_PWMPIN)
        self._motors["rear_left"] = Motor(REAR_LEFT_WHEEL_PIN_A, REAR_LEFT_WHEEL_PIN_B, REAR_LEFT_WHEEL_PWMPIN)
        self._motors["rear_right"] = Motor(REAR_RIGHT_WHEEL_PIN_A, REAR_RIGHT_WHEEL_PIN_B, REAR_RIGHT_WHEEL_PWMPIN)

        self._speed = 0
        self.state = 0
        self.set_speed(100)
        return


    def set_speed(self, speed):
        self._speed = speed
        for key in self._motors:
            self._motors[key].setspeed(speed)
        return


    def turn_left(self):
        print("turn_left : run")
        for key in self._motors:
            if "rear" in key:
                self._motors[key].setspeed(int(self._speed * 0.7))
            else:
                self._motors[key].setspeed(self._speed)

            if "left" in key:
                self._motors[key].accelon(back=True)
            if "right" in key:
                self._motors[key].accelon()
        print("turn_left : over")
        return


    def turn_right(self):
        print("turn_right : run")
        for key in self._motors:
            if "rear" in key:
                self._motors[key].setspeed(int(self._speed * 0.7))
            else:
                self._motors[key].setspeed(self._speed)

            if "left" in key:
                self._motors[key].accelon()
            if "right" in key:
                self._motors[key].accelon(back=True)
        print("turn_right : over")
        return


    def forward(self):
        print("forward : run")
        for key in self._motors:
            self._motors[key].setspeed(self._speed)
            self._motors[key].accelon()
        print("forward : over")
        return


    def back(self):
        print("back : run")
        for key in self._motors:
            self._motors[key].setspeed(self._speed)
            self._motors[key].accelon(back=True)
        print("back : over")
        return


    def brake(self):
        print("brake : run")
        for key in self._motors:
            self._motors[key].brakeon()
        print("brake : over")
        return


    def acceloff(self):
        print("acceloff : run")
        for key in self._motors:
            self._motors[key].acceloff()
        print("acceloff : over")
        return


    def debug_proc(self):
        time.sleep(5)
        # Check for each tire
        # for key in self._motors:
        #     print(key)
        #     time.sleep(1)
        #     self._motors[key].setspeed(100)
        #     self._motors[key].accelon()
        #     time.sleep(1)
        #     self._motors[key].accelon(back=True)
        #     time.sleep(1)
        #     self._motors[key].acceloff()

        # Check : operation function
        self.forward()
        time.sleep(1)
        self.brake()
        time.sleep(1)
        self.turn_left()
        time.sleep(1)
        self.turn_right()
        time.sleep(1)
        self.acceloff()
        time.sleep(1)
        self.back()
        time.sleep(1)
        self.acceloff()



if __name__ == '__main__':
    pi_car = PiCar()
    pi_car.debug_proc()

```

下記のコマンドを実行で、動作確認をします。

```
 $ python picar.py
```

正しく動作すれば、
前進→ブレーキ→左旋回→右旋回→停止→バック→停止
の順に動作します。


# さいごに

次の記事が最後の予定です。
ネットワーク越しに制御したいと思います。


# 参考

* [ラズパイで動くモノを作る](https://note.com/takasi7/n/ncfc48ab9b851)