2021年7月15日木曜日

Raspberry Pi Zeroと小型ターンテーブルをREST APIで制御する

サーボモーターと3Dプリンターで作成した小型ターンテーブルをRaspberry Pi Zero上のREST APIで制御するには、以下の手順を実行します。

〇Raspberry Pi Zeroとターンテーブル

開発手順

1. 回転台部分の作成
OpenSCADで以下のファイルを実行し、回転部分のモデルをSTLで保存します。保存したSTLファイルをUltimaker Curaでgcodeにスライスして3Dプリンターで印刷します。

〇OpenSCADの回転部分の画面

// servo TURNTABLE
TURNTABLE_DIAMETER_L=42;
TURNTABLE_HEIGHT_L=3;
TURNTABLE_DIAMETER_LL=47;
TURNTABLE_HEIGHT_LL=2;

// servoアームシャフト部分の穴
LARGE_HOLE_HEIGHT=0.0;
LARGE_HOLE_DIAMETER=7.8;
ARM_HEIGHT=2;
SPACE_HOLE=15;
SMALL_HOLE_RADIUS=4.2/2;

// アーム固定用ネジ穴
SCREW_HOLE_POS=8.5;
SCREW_HOLE_DIAMETER=1+1;
SCREW_HOLE_HEIGHT=10;

difference(){
    union(){
        translate([0, 0, 0])
        linear_extrude(height=TURNTABLE_HEIGHT_L){
            circle(TURNTABLE_DIAMETER_L/2, $fn=50);
        }
        translate([0, 0, -TURNTABLE_HEIGHT_LL])
        linear_extrude(height=TURNTABLE_HEIGHT_LL){
            circle(TURNTABLE_DIAMETER_LL/2, $fn=50);
        }
    }
    union(){
        translate([0, 0, TURNTABLE_HEIGHT_L-(LARGE_HOLE_HEIGHT+ARM_HEIGHT)-0.5])
        linear_extrude(height=LARGE_HOLE_HEIGHT+ARM_HEIGHT){
            circle(LARGE_HOLE_DIAMETER/2, $fn=50);
        }
        translate([0, 0, TURNTABLE_HEIGHT_L-ARM_HEIGHT])
        linear_extrude(height=ARM_HEIGHT){
            polygon(points = [
              [0, LARGE_HOLE_DIAMETER/2],
              [0, -LARGE_HOLE_DIAMETER/2],
              [SPACE_HOLE, -SMALL_HOLE_RADIUS],
              [SPACE_HOLE, SMALL_HOLE_RADIUS]
            ]);
            polygon(points = [
              [0, LARGE_HOLE_DIAMETER/2],
              [0, -LARGE_HOLE_DIAMETER/2],
              [-SPACE_HOLE, -SMALL_HOLE_RADIUS],
              [-SPACE_HOLE, SMALL_HOLE_RADIUS]
            ]);
        }
        translate([SCREW_HOLE_POS, 0, TURNTABLE_HEIGHT_L-(ARM_HEIGHT+SCREW_HOLE_HEIGHT)])
        linear_extrude(height=ARM_HEIGHT+SCREW_HOLE_HEIGHT){
            circle(SCREW_HOLE_DIAMETER/2, $fn=50);
        }
        translate([-SCREW_HOLE_POS, 0, TURNTABLE_HEIGHT_L-(ARM_HEIGHT+SCREW_HOLE_HEIGHT)])
        linear_extrude(height=ARM_HEIGHT+SCREW_HOLE_HEIGHT){
            circle(SCREW_HOLE_DIAMETER/2, $fn=50);
        }

    }
}

2. 回転台を支える天板部分の作成
OpenSCADで以下のファイルを実行し、回転台を支える天板部分のモデルをSTLで保存します。保存したSTLファイルをUltimaker Curaでgcodeにスライスして3Dプリンターで印刷します。

〇OpenSCADの回転台を支える天板部分の画面

// TURNTABLE 天板
TURNTABLE_DIAMETER_L=42+1;
TURNTABLE_HEIGHT_L=3;
TURNTABLE_DIAMETER_LL=47+1;
TURNTABLE_HEIGHT_LL=2;
// 箱の大きさ
MOUNTER_THICK=2;
BOX_SIZE=50;

difference(){
    union(){
        translate([-BOX_SIZE/2, -BOX_SIZE/2, 0])
        linear_extrude(height=TURNTABLE_HEIGHT_L+TURNTABLE_HEIGHT_LL){
                square([BOX_SIZE, BOX_SIZE]);
        }
    }
    union(){
        translate([0, 0, 0])
        linear_extrude(height=TURNTABLE_HEIGHT_L){
            circle(TURNTABLE_DIAMETER_L/2, $fn=50);
        }
        translate([0, 0, TURNTABLE_HEIGHT_L])
        linear_extrude(height=TURNTABLE_HEIGHT_LL){
            circle(TURNTABLE_DIAMETER_LL/2, $fn=50);
        }
    }
}

3. サーボモーター固定台の作成
OpenSCADで以下のファイルを実行し、サーボモーター固定台のモデルをSTLで保存します。保存したSTLファイルをUltimaker Curaでgcodeにスライスして3Dプリンターで印刷します。

〇OpenSCADのサーボモーター固定台の画面

// サーボモーター固定台
MOUNTER_THICK=2;
BOX_SIZE=50-MOUNTER_THICK*2;

MOUNTER_W=23;
MOUNTER_D=9;
HOLE_RADIUS=0.6;

HANDLE_W = 5;
HANDLE_H=12.2;

SERVO_BOTTOM=7;
SERVO_OFFSET=12.2;
HOLE2_DIAMETER=3; // 穴の大きさは適宜変更してください

module mounter2()
{
    difference()
    {
        union()
        {
            translate([-HANDLE_W-SERVO_OFFSET/2, 0, 0])
            linear_extrude(height=MOUNTER_THICK){
                square([MOUNTER_W+HANDLE_W*2, MOUNTER_D]);
            }

            translate([-HANDLE_W-SERVO_OFFSET/2, 0, MOUNTER_THICK])
            linear_extrude(height=HANDLE_H){
                square([HANDLE_W, MOUNTER_D]);
            }
            translate([MOUNTER_W-SERVO_OFFSET/2, 0, MOUNTER_THICK])
            linear_extrude(height=HANDLE_H){
                square([HANDLE_W, MOUNTER_D]);
            }
        }
        rotate([-90,0,0])
        translate([-HANDLE_W/2-SERVO_OFFSET/2, -MOUNTER_THICK-HANDLE_H/2, 0])
        linear_extrude(height=MOUNTER_D){
            circle(HOLE_RADIUS, $fn=50);
        }

        rotate([-90,0,0])
        translate([MOUNTER_W+HANDLE_W/2-SERVO_OFFSET/2, -MOUNTER_THICK-HANDLE_H/2, 0])
        linear_extrude(height=MOUNTER_D){
            circle(HOLE_RADIUS, $fn=50);
        }

    }   

    // servo motor直下
    translate([-BOX_SIZE/2, MOUNTER_D, 0])
    linear_extrude(height=MOUNTER_THICK){
        square([BOX_SIZE, SERVO_BOTTOM]);
    }
    translate([-BOX_SIZE/2, MOUNTER_D+SERVO_BOTTOM, 0])
        linear_extrude(height=HANDLE_H+MOUNTER_THICK){
            square([BOX_SIZE, MOUNTER_THICK]);
    }

}
mounter2();

4. ターンテーブル底板の作成
OpenSCADで以下のファイルを実行し、ターンテーブル底板のモデルをSTLで保存します。保存したSTLファイルをUltimaker Curaでgcodeにスライスして3Dプリンターで印刷します。

〇OpenSCADのターンテーブル底板の画面

// ターンテーブルの底版
THICK=2;
BOX_SIZE=50;

// サーボモーター固定台の幅
SERVO_W=14.4;

difference(){
    union(){
        translate([-BOX_SIZE/2, -BOX_SIZE/2, 0])
        linear_extrude(height=THICK){
                square([BOX_SIZE, BOX_SIZE]);
        }
                
        translate([-BOX_SIZE/2+THICK, -BOX_SIZE/2+THICK, THICK])
        linear_extrude(height=THICK){
                square([BOX_SIZE-THICK*2, BOX_SIZE-THICK*2]);
        }
    }
    translate([-SERVO_W/2, -BOX_SIZE/2+THICK, THICK])
    linear_extrude(height=THICK){
            square([SERVO_W, BOX_SIZE-THICK*2]);
    }
}

5. ターンテーブル側面の作成
OpenSCADで以下のファイルを実行し、ターンテーブル側面のモデルをSTLで保存します。保存したSTLファイルをUltimaker Curaでgcodeにスライスして3Dプリンターで印刷します。

〇OpenSCADのターンテーブル側面の画面

// ターンテーブルの側面
BOX_THICK=2;
BOX_SIZE=50;
BOX_HEIGHT=31.4;

// サーボモーター接続用ケーブルの穴
CABLE_HOLE_W=6;
CABLE_HOLE_H=2;

difference(){
    union(){
        translate([-BOX_SIZE/2, -BOX_SIZE/2, 0])
        linear_extrude(height=BOX_HEIGHT){
                square([BOX_SIZE, BOX_THICK]);
        }

        translate([-BOX_SIZE/2, BOX_SIZE/2-BOX_THICK, 0])
        linear_extrude(height=BOX_HEIGHT){
                square([BOX_SIZE, BOX_THICK]);
        }

        translate([-BOX_SIZE/2, -BOX_SIZE/2, 0])
        linear_extrude(height=BOX_HEIGHT){
                square([BOX_THICK, BOX_SIZE]);
        }

        translate([BOX_SIZE/2-BOX_THICK, -BOX_SIZE/2, 0])
        linear_extrude(height=BOX_HEIGHT){
                square([BOX_THICK, BOX_SIZE]);
        }
    }
    translate([-CABLE_HOLE_W/2, -BOX_SIZE/2, BOX_HEIGHT-CABLE_HOLE_H])
    linear_extrude(height=CABLE_HOLE_H){
            square([CABLE_HOLE_W, BOX_THICK]);
    }

}

6. 3Dプリンターで作成した部品の確認
この時点で以下の写真のような5つの部品があるので、適宜バリなどを取っておきます。

7. 回転部分とサーボモーター付属のアームのネジ止め
回転部分とサーボモーター付属のアームをネジ止めします。

8. 底板とサーボモーター固定台の接着
タミヤセメントなどの接着剤を使用して、底板とサーボモーター固定台を接着します。接着剤を塗って接着した後、クリップなどで固定しておきます。
サーボモーターが中心に来るように、底板部分の短い板の部分とサーボモーターの垂直部分が同じ側になるように接着します。

9. サーボモーターの取り付け
以下の秋月電子さんで販売しているサーボモーターをサーボモーター固定台にネジ止めします。このとき、サーボモーターのシャフトが中心側に来るように取り付けます。

360°連続回転サーボ(ローテーションサーボ) SG90-HV
https://akizukidenshi.com/catalog/g/gM-14382/


10.回転台を支える天板部分と側面部分の接着
タミヤセメントなどの接着剤を使用して、回転台を支える天板部分と側面部分を接着します。完全に固定されるまで、重しなどを乗せておきます。

11. 手順9と手順10で作成した部品をはめ込む
手順9で作成した部品と手順10で作成した部品をはめ込むと以下の様な写真の状態になります。サーボモーターのケーブルは側面の窪みのところから外部へ出します。

12. サーボモーターとRaspberry Pi Zeroの接続と回転部分のはめ込み
サーボモーターのケーブルとRaspberry Pi Zeroをジャンパ線などで以下の様に接続します。
下図の4番ピン(5V power)→サーボモーターのオレンジ色のケーブル端子
下図の6番ピン(Ground)→サーボモーターの茶色のケーブル端子
下図の32番ピン(PWM0)→サーボモーターの黄色のケーブル端子

配線が終了したら最後に回転部分をはめ込みます

13. Raspberry Pi Zeroにpipenvの導入
pipenvをインストールしていない場合は、以下のコマンドを実行します。
sudo apt-get update

sudo apt-get -y install python3-pip python3-distutils python3-dev

sudo pip3 install --upgrade pip

sudo pip3 install --upgrade setuptools

sudo pip3 install pipenv

echo "export PIPENV_VENV_IN_PROJECT=true" >> ~/.bashrc

source ~/.bashrc

14. flaskとRpi.GPIOモジュールがインストールされた仮想環境を作成する
pipenvを使用する場合は以下のコマンドで、REST API用の仮想環境を作成します。REST APIを実装するためにflask、サーボモーターを制御するためにRPi.GPIOをインストールします。
mkdir -p ~/turntable

cd ~/turntable

pipenv --python 3

pipenv install flask

pipenv shell

python -m pip install RPi.GPIO

15. Flask REST APIアプリケーションの作成
/turntableに回転速度を指定するdegreeパラメータと動作秒数を指定するdurationパラメータでアクセスしたとき、サーボモーターを回転するようにします。

app.py
from flask import Flask, jsonify, request
import time
import RPi.GPIO as GPIO


GPIO.setmode(GPIO.BCM)
GPIO.setup(12, GPIO.OUT)


app = Flask(__name__)

@app.route('/turntable')
def turntable():
  degree = int(request.args.get('degree', ''))
  duration = int(request.args.get('duration', ''))
  pwm = GPIO.PWM(12, 50) # pin=12, 50Hz
  pwm.start(0)
  pwm.ChangeDutyCycle( 2.5 + (12.0-2.5)/180*(degree+90))
  time.sleep(duration)
  pwm.stop()
  return {"status":"ok"}

16. 実行
Flaskを実行するには、以下のコマンドを実行します。
export FLASK_APP=app.py

flask run -h 0.0.0.0

ブラウザから以下のアドレスにアクセスします。小型ターンテーブルがゆっくりと2秒間回転する事を確認します。
http://<Raspberry Pi ZeroのIP>:5000/turntable?degree=1&duration=2

関連情報

・そのほかの3Dプリンターを活用した記事は以下を参照してください。
OpenSCADまとめ

・Raspberry Pi Zeroに関する他の記事は、こちらを参照してください。

0 件のコメント:

コメントを投稿