Pythonでボールねじとモーターとカップリングの選定をしてみる 改良編
2020/03/16 categories:Python| tags:Python|Mechanical design|
以前作ったボールねじ、モーター、カップリング選定プログラムを改良しました。
改良点
- 計算式ミスを修正
- 安全率を指定して計算結果の出力を絞り込む
座屈荷重や許容荷重などの軸方向荷重に関する計算式がミスっていたので修正しました。前回はそれぞれの計算を関数化して計算していましたが、わざわざ関数に分ける必要もないのでcalculate()という一つの関数で計算するようにしました。その他には、ストロークを指定してストロークを満たしたボールねじのみ抽出して計算して、計算結果から安全率以下を省き、処理は20000通り毎に分割するように変更したことで、処理を限定的に行うようにしました。
ストロークの限定
bs = bs[( (bs['l0min'] < stroke) & (bs['l0max'] > stroke) )]
bs['l1'] = bs['l7'] + bs['l8'] + stroke
bs['l0'] = bs['l1'] + bs['l2'] + bs['l3'] + bs['l4'] + bs['l5']
計算結果を安全率で絞込み
計算結果と計算条件をすべてdfに入れて、計算した安全率sf_sl~sf_mt_d0と比較すると一致した行がTrue、一致しなければFalseになる配列が得られるので、df[]でそのブーリアンの配列を指定すると、安全率で絞り込まれた計算結果が得られます。
flags = (df['sf_sl'] >= sf)
flags &= (df['sf_bl'] >= sf)
flags &= (df['sf_yl'] >= sf)
flags &= (df['sf_cs'] >= sf)
flags &= (df['sf_ir'] >= sf)
flags &= (df['sf_t'] >= sf)
flags &= (df['sf_mt_n'] >= sf)
flags &= (df['sf_bs_d3'] >= sf)
flags &= (df['sf_mt_d0'] >= sf)
df = df[flags]
計算結果
ボールねじのパラメータ、カップリングのパラメータ、モーターのパラメータ、安全率というcsvです。
所感
計算関連の部分はこのくらいで良さげです。次は簡単に操作できるようにGUIを作ってみたいと思いますが、その前にPyQt5のQTableViewでPandasのDataFrameを表示するプログラムを作成したいと思います。
ソースコード
## -*- coding: utf-8 -*-
import itertools
import math
import numpy as np
import pandas as pd
def calculate(_bs, _cp, _mt, sf, stroke, velocity, acceleration, buckling_load_factor, static_allowable_load_factor,
load_factor, critical_speed_factor, work_mass, guide_friction_factor, guide_friction):
'''
bs : ボールねじリスト(pandasデータフレーム)
cp : カップリングリスト(pandasデータフレーム)
mt : モーターリスト(pandasデータフレーム)
sf : 安全率
velocity : 速度[m/s]
acceleration : 加速度[m/ss]
buckling_load_factor : 座屈荷重係数 19.9, 10.0, 1.2, 5.0
static_allowable_load_factor : 静的許容荷重係数 1.0~2.0, 1.5~3.0
load_factor : 荷重係数 1.0~1.2, 1.2~1.5, 1.5~3.0
critical_speed_factor : 危険速度係数 21.9, 15.1, 9.7, 3.4
work_mass : ワーク質量[kg]
guide_friction_factor : 案内面摩擦係数
guide_friction : 案内面抵抗[N]
'''
# データフレームをコピー
bs = _bs.copy()
bs.insert(0, 'model', bs.index)
cp = _cp.copy()
cp.insert(0, 'model', cp.index)
mt = _mt.copy()
mt.insert(0, 'model', mt.index)
# ストロークを満たす行を抽出
bs = bs[( (bs['l0min'] < stroke) & (bs['l0max'] > stroke) )]
bs['l1'] = bs['l7'] + bs['l8'] + stroke
bs['l0'] = bs['l1'] + bs['l2'] + bs['l3'] + bs['l4'] + bs['l5']
# 全通りの組み合わせリストを作成
df = pd.DataFrame(itertools.product(bs.values, cp.values, mt.values))
df = pd.concat([
pd.DataFrame(df[0].tolist(), columns= 'bs_' + bs.columns),
pd.DataFrame(df[1].tolist(), columns= 'cp_' + cp.columns),
pd.DataFrame(df[2].tolist(), columns= 'mt_' + mt.columns)
], axis=1)
df['v'] = velocity # 速度[m/s]
df['a'] = acceleration # 加速度[m/ss]
df['m'] = buckling_load_factor # 座屈荷重係数 19.9, 10.0, 1.2, 5.0
df['fs'] = static_allowable_load_factor # 静許容荷重係数 1.0~2.0, 1.5~3.0
df['fw'] = load_factor # 荷重係数 1.0~1.2, 1.2~1.5, 1.5~3.0
df['f'] = critical_speed_factor # 危険速度係数 21.9, 15.1, 9.7, 3.4
df['mw'] = work_mass # ワーク質量[kg]
# ボールねじ計算
df['n'] = df['v'] * 60000.0 / df['bs_l6'] # 回転数
df['at'] = df['v'] / df['a'] # 加速時間 [sec]
df['Fa'] = -1.0 * guide_friction_factor * df['mw'] * 9.80665 + guide_friction + df['mw'] * df['a'] # 軸方向最大荷重 [N] -myu * mg + ff + ma
df['P1'] = df['m'] * np.power(df['bs_d1'], 4.0) * 10000.0 / np.power(( df['bs_l3'] / 2.0 + df['bs_l2'] + df['bs_l1'] - df['bs_l7'] / 2.0 ),2.0) # 座屈荷重
df['P2'] = 115.45353 * np.power(df['bs_d1'], 2.0) # 降伏荷重
df['P0'] = df['bs_C0a'] / df['fs'] # 静最大許容荷重
df['nc'] = df['f'] * df['bs_d1'] * 10000000.0 / np.power(( df['bs_l5'] + df['bs_l1'] - df['bs_l8'] - df['bs_l7']/2.0 ),2.0) # 危険速度
df['L'] = np.power( ( df['bs_Ca']/(df['Fa']*df['fw']) ) , 3.0) * 1000000.0 # 寿命回転数
df['Lt'] = df['L'] / 60.0 / df['n'] # 寿命時間
df['Ls'] = df['L'] * df['bs_l6'] * 0.000001 # 寿命距離
# モーター計算
df['ar'] = 2.0 * math.pi * df['n'] / 60.0 / df['at'] # 角加速度 [rad/ss]
df['Iw'] = df['mw'] * ( df['bs_l6']*0.001 / math.pi )**2.0 /4.0 # ワークのイナーシャ m*(l/pi)^2/4
df['Is'] = math.pi * 0.24375 * df['bs_l0'] * df['bs_d0']**4.0 * 0.000000000001 # ボールねじ軸のイナーシャ [kg*m**2]
df['Ir'] = ( df['Is'] + df['Iw'] + df['cp_i'] ) / df['mt_i'] # イナーシャ比 = モーター以外のイナーシャ合計 / モーターのイナーシャ
df['t'] = ( df['Is'] + df['Iw'] + df['cp_i'] + df['mt_i'] ) * df['ar'] # トルク = イナーシャ合計 * 角加速度
# 安全率計算
df['sf_sl'] = df['P0'] / df['Fa'] # 静最大許容荷重
df['sf_bl'] = df['P1'] / df['Fa'] # 座屈荷重
df['sf_yl'] = df['P2'] / df['Fa'] # 降伏荷重
df['sf_cs'] = df['nc'] / df['n'] # 危険速度
df['sf_ir'] = df['mt_ir'] / df['Ir'] # イナーシャ比
df['sf_t'] = df['mt_t0'] / df['t'] # トルク
df['sf_mt_n'] = df['mt_nmax'] / df['n'] # モーター回転数
df['sf_bs_d3'] = 999.0 # ボールねじシャンク径
df['sf_bs_d3'].where( (df['cp_d1'] <= df['bs_d3']) & (df['bs_d3'] <= df['cp_d2']), 0.0, inplace=True)
df['sf_mt_d0'] = 999.0 # モーター軸径
df['sf_mt_d0'].where( (df['cp_d1'] <= df['mt_d0']) & (df['mt_d0'] <= df['cp_d2']), 0.0, inplace=True)
# 安全率で絞り込み
flags = (df['sf_sl'] >= sf)
flags &= (df['sf_bl'] >= sf)
flags &= (df['sf_yl'] >= sf)
flags &= (df['sf_cs'] >= sf)
flags &= (df['sf_ir'] >= sf)
flags &= (df['sf_t'] >= sf)
flags &= (df['sf_mt_n'] >= sf)
flags &= (df['sf_bs_d3'] >= sf)
flags &= (df['sf_mt_d0'] >= sf)
return df[flags]
def main():
# csv読み込み
bs = pd.read_csv('ballscrew.csv', encoding='utf-8', index_col=0).astype(float)
cp = pd.read_csv('coupling.csv', encoding='utf-8', index_col=0).astype(float)
mt = pd.read_csv('motor.csv', encoding='utf-8', index_col=0).astype(float)
df = calculate(
bs, # ボールねじリスト
cp, # カップリングリスト
mt, # モーターリスト
1.0, # 安全率
600.0, # ストローク[mm]
1.0, # 速度[m/s]
10.0, # 加速度[m/ss]
19.9, # 座屈荷重係数 19.9, 10.0, 1.2, 5.0
2.0, # 静許容荷重係数 1.0~2.0, 1.5~3.0
1.5, # 荷重係数 1.0~1.2, 1.2~1.5, 1.5~3.0
15.1, # 危険速度係数 21.9, 15.1, 9.7, 3.4
20.0, # ワーク質量[kg]
0.003, # 案内面摩擦係数
15.0 # 案内面の抵抗[N]
)
df.to_csv("output.csv")
if __name__ == '__main__':
main()