| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- // 伺服驱动选型工具 - 核心计算逻辑
- class ServoSizer {
- constructor() {
- this.currentType = 'ballScrew';
- this.init();
- }
- init() {
- this.bindEvents();
- this.updateUI();
- this.loadDefaults();
- }
- bindEvents() {
- // 传动类型切换
- document.querySelectorAll('.transmission-type').forEach(btn => {
- btn.addEventListener('click', (e) => {
- this.currentType = e.target.dataset.type;
- this.updateUI();
- this.clearResults();
- });
- });
- // 输入验证
- document.querySelectorAll('input[type="number"]').forEach(input => {
- input.addEventListener('input', () => {
- this.validateInput(input);
- });
- });
- // 计算按钮
- document.getElementById('calculateBtn').addEventListener('click', () => {
- this.calculate();
- });
- // 重置按钮
- document.getElementById('resetBtn').addEventListener('click', () => {
- this.resetForm();
- });
- // 导出按钮
- document.getElementById('exportBtn').addEventListener('click', () => {
- this.exportResults();
- });
- }
- validateInput(input) {
- const value = parseFloat(input.value);
- const min = parseFloat(input.min) || -Infinity;
- const max = parseFloat(input.max) || Infinity;
-
- if (value < min || value > max) {
- input.classList.add('error');
- } else {
- input.classList.remove('error');
- }
- }
- loadDefaults() {
- // 加载默认值
- const defaults = {
- friction: 0.1,
- efficiency: 0.9,
- safetyFactor: 1.5,
- inertiaRatio: 10
- };
-
- Object.keys(defaults).forEach(key => {
- const input = document.querySelector(`[name="${key}"]`);
- if (input) input.value = defaults[key];
- });
- }
- updateUI() {
- // 隐藏所有传动类型表单
- document.querySelectorAll('.transmission-form').forEach(form => {
- form.style.display = 'none';
- });
-
- // 显示当前选中的传动类型表单
- const currentForm = document.getElementById(`${this.currentType}Form`);
- if (currentForm) currentForm.style.display = 'block';
-
- // 更新按钮状态
- document.querySelectorAll('.transmission-type').forEach(btn => {
- btn.classList.remove('active');
- });
- document.querySelector(`[data-type="${this.currentType}"]`).classList.add('active');
-
- // 更新标题
- const titles = {
- ballScrew: '滚珠丝杠传动',
- timingBelt: '同步带传动',
- gearbox: '减速机传动',
- turntable: '转盘传动',
- winding: '收放卷传动',
- directDrive: '直接驱动'
- };
- document.getElementById('currentTypeTitle').textContent = titles[this.currentType] || '伺服驱动选型';
- }
- // 滚珠丝杠计算
- calculateBallScrew(params) {
- const {
- loadMass, screwDiameter, screwLead, friction, efficiency,
- maxSpeed, accelerationTime, travelDistance
- } = params;
- // 转换为标准单位
- const lead = screwLead / 1000; // mm to m
- const diameter = screwDiameter / 1000; // mm to m
-
- // 1. 负载转矩计算
- const gravity = 9.81;
- const frictionForce = loadMass * gravity * friction;
- const frictionTorque = (frictionForce * diameter) / 2;
-
- // 推力转矩 (忽略效率先)
- const thrustTorque = (loadMass * gravity * lead) / (2 * Math.PI);
- const totalTorque = (thrustTorque + frictionTorque) / efficiency;
-
- // 2. 转速计算
- const maxRpm = (maxSpeed * 60) / (lead * 1000); // mm/s to rpm
-
- // 3. 惯量计算
- const screwInertia = (Math.PI * 7800 * Math.pow(diameter, 4) * travelDistance) / (32 * Math.pow(lead, 2));
- const loadInertia = loadMass * Math.pow(lead / (2 * Math.PI), 2);
- const totalInertia = screwInertia + loadInertia;
-
- // 4. 加速度转矩
- const angularAccel = (maxRpm * 2 * Math.PI / 60) / accelerationTime;
- const accelTorque = totalInertia * angularAccel;
-
- // 5. 峰值转矩
- const peakTorque = totalTorque + accelTorque;
-
- // 6. 功率计算
- const power = (peakTorque * maxRpm * 2 * Math.PI) / 60;
-
- return {
- speedRange: { min: 0, max: maxRpm },
- torque: { continuous: totalTorque, peak: peakTorque },
- inertia: { motor: 0, load: totalInertia, ratio: totalInertia / 0.001 }, // 假设电机惯量
- power: { required: power, rated: power * 1.2 }
- };
- }
- // 同步带计算
- calculateTimingBelt(params) {
- const {
- loadMass, pulleyDiameter, friction, efficiency,
- maxSpeed, accelerationTime
- } = params;
- const radius = pulleyDiameter / 2000; // mm to m
-
- // 负载转矩
- const gravity = 9.81;
- const frictionForce = loadMass * gravity * friction;
- const loadTorque = (loadMass * gravity * radius + frictionForce * radius) / efficiency;
-
- // 转速
- const maxRpm = (maxSpeed * 60) / (Math.PI * pulleyDiameter);
-
- // 惯量
- const pulleyInertia = 0.5 * 0.1 * Math.pow(radius, 2); // 假设滑轮质量0.1kg
- const loadInertia = loadMass * Math.pow(radius, 2);
- const totalInertia = pulleyInertia + loadInertia;
-
- // 加速度转矩
- const angularAccel = (maxRpm * 2 * Math.PI / 60) / accelerationTime;
- const accelTorque = totalInertia * angularAccel;
-
- const peakTorque = loadTorque + accelTorque;
- const power = (peakTorque * maxRpm * 2 * Math.PI) / 60;
-
- return {
- speedRange: { min: 0, max: maxRpm },
- torque: { continuous: loadTorque, peak: peakTorque },
- inertia: { motor: 0, load: totalInertia, ratio: totalInertia / 0.001 },
- power: { required: power, rated: power * 1.2 }
- };
- }
- // 减速机计算
- calculateGearbox(params) {
- const {
- loadInertia, loadTorque, gearRatio, efficiency,
- maxSpeed, accelerationTime
- } = params;
- // 折算到电机侧
- const reflectedInertia = loadInertia / Math.pow(gearRatio, 2);
- const reflectedTorque = loadTorque / (gearRatio * efficiency);
-
- // 电机转速
- const motorRpm = maxSpeed * gearRatio;
-
- // 加速度转矩
- const angularAccel = (motorRpm * 2 * Math.PI / 60) / accelerationTime;
- const accelTorque = reflectedInertia * angularAccel;
-
- const peakTorque = reflectedTorque + accelTorque;
- const power = (peakTorque * motorRpm * 2 * Math.PI) / 60;
-
- return {
- speedRange: { min: 0, max: motorRpm },
- torque: { continuous: reflectedTorque, peak: peakTorque },
- inertia: { motor: 0, load: reflectedInertia, ratio: reflectedInertia / 0.001 },
- power: { required: power, rated: power * 1.2 }
- };
- }
- // 转盘计算
- calculateTurntable(params) {
- const {
- tableMass, tableRadius, friction, efficiency,
- maxSpeed, accelerationTime
- } = params;
- const radius = tableRadius / 1000; // mm to m
-
- // 转盘惯量 (实心圆盘)
- const tableInertia = 0.5 * tableMass * Math.pow(radius, 2);
-
- // 摩擦转矩
- const gravity = 9.81;
- const frictionTorque = tableMass * gravity * friction * radius;
-
- // 转速
- const maxRpm = maxSpeed;
-
- // 加速度转矩
- const angularAccel = (maxRpm * 2 * Math.PI / 60) / accelerationTime;
- const accelTorque = tableInertia * angularAccel;
-
- const peakTorque = (frictionTorque + accelTorque) / efficiency;
- const power = (peakTorque * maxRpm * 2 * Math.PI) / 60;
-
- return {
- speedRange: { min: 0, max: maxRpm },
- torque: { continuous: frictionTorque / efficiency, peak: peakTorque },
- inertia: { motor: 0, load: tableInertia, ratio: tableInertia / 0.001 },
- power: { required: power, rated: power * 1.2 }
- };
- }
- // 收放卷计算
- calculateWinding(params) {
- const {
- materialDensity, materialWidth, initialDiameter, finalDiameter,
- lineSpeed, tension, accelerationTime
- } = params;
- const initialRadius = initialDiameter / 2000; // mm to m
- const finalRadius = finalDiameter / 2000;
- const width = materialWidth / 1000;
-
- // 卷筒惯量 (空心圆柱)
- const initialMass = materialDensity * Math.PI * (Math.pow(finalRadius, 2) - Math.pow(initialRadius, 2)) * width;
- const initialInertia = 0.5 * initialMass * (Math.pow(finalRadius, 2) + Math.pow(initialRadius, 2));
-
- // 张力转矩
- const tensionTorque = tension * finalRadius;
-
- // 转速范围
- const minRpm = (lineSpeed * 60) / (Math.PI * finalDiameter);
- const maxRpm = (lineSpeed * 60) / (Math.PI * initialDiameter);
-
- // 加速度转矩 (使用最大惯量)
- const angularAccel = (maxRpm * 2 * Math.PI / 60) / accelerationTime;
- const accelTorque = initialInertia * angularAccel;
-
- const peakTorque = tensionTorque + accelTorque;
- const power = (peakTorque * maxRpm * 2 * Math.PI) / 60;
-
- return {
- speedRange: { min: minRpm, max: maxRpm },
- torque: { continuous: tensionTorque, peak: peakTorque },
- inertia: { motor: 0, load: initialInertia, ratio: initialInertia / 0.001 },
- power: { required: power, rated: power * 1.2 }
- };
- }
- // 直接驱动计算
- calculateDirectDrive(params) {
- const {
- loadInertia, frictionTorque, maxSpeed, accelerationTime
- } = params;
- // 直接驱动,无传动比
- const motorRpm = maxSpeed;
-
- // 加速度转矩
- const angularAccel = (motorRpm * 2 * Math.PI / 60) / accelerationTime;
- const accelTorque = loadInertia * angularAccel;
-
- const peakTorque = frictionTorque + accelTorque;
- const power = (peakTorque * motorRpm * 2 * Math.PI) / 60;
-
- return {
- speedRange: { min: 0, max: motorRpm },
- torque: { continuous: frictionTorque, peak: peakTorque },
- inertia: { motor: 0, load: loadInertia, ratio: loadInertia / 0.001 },
- power: { required: power, rated: power * 1.2 }
- };
- }
- getFormValues() {
- const form = document.getElementById(`${this.currentType}Form`);
- const inputs = form.querySelectorAll('input[type="number"]');
- const values = {};
-
- inputs.forEach(input => {
- const name = input.name;
- const value = parseFloat(input.value) || 0;
- values[name] = value;
- });
-
- // 获取通用参数
- const friction = parseFloat(document.querySelector('[name="friction"]').value) || 0.1;
- const efficiency = parseFloat(document.querySelector('[name="efficiency"]').value) || 0.9;
- const safetyFactor = parseFloat(document.querySelector('[name="safetyFactor"]').value) || 1.5;
- const inertiaRatio = parseFloat(document.querySelector('[name="inertiaRatio"]').value) || 10;
-
- return { ...values, friction, efficiency, safetyFactor, inertiaRatio };
- }
- calculate() {
- const params = this.getFormValues();
-
- // 验证输入
- if (!this.validateInputs(params)) {
- this.showAlert('请检查输入参数是否有效', 'error');
- return;
- }
-
- let results;
- try {
- switch (this.currentType) {
- case 'ballScrew':
- results = this.calculateBallScrew(params);
- break;
- case 'timingBelt':
- results = this.calculateTimingBelt(params);
- break;
- case 'gearbox':
- results = this.calculateGearbox(params);
- break;
- case 'turntable':
- results = this.calculateTurntable(params);
- break;
- case 'winding':
- results = this.calculateWinding(params);
- break;
- case 'directDrive':
- results = this.calculateDirectDrive(params);
- break;
- default:
- throw new Error('未知的传动类型');
- }
-
- // 应用安全系数
- results.torque.continuous *= params.safetyFactor;
- results.torque.peak *= params.safetyFactor;
- results.power.rated *= params.safetyFactor;
-
- this.displayResults(results);
- this.showAlert('计算完成!', 'success');
-
- } catch (error) {
- console.error('计算错误:', error);
- this.showAlert('计算出错: ' + error.message, 'error');
- }
- }
- validateInputs(params) {
- // 基本验证
- for (let key in params) {
- if (params[key] < 0) return false;
- if (isNaN(params[key])) return false;
- }
- return true;
- }
- displayResults(results) {
- const resultsDiv = document.getElementById('results');
- resultsDiv.innerHTML = `
- <div class="result-card">
- <h3>计算结果</h3>
- <div class="result-grid">
- <div class="result-item">
- <label>转速范围 (RPM)</label>
- <div class="result-value">${results.speedRange.min.toFixed(1)} - ${results.speedRange.max.toFixed(1)}</div>
- </div>
- <div class="result-item">
- <label>连续转矩 (N·m)</label>
- <div class="result-value">${results.torque.continuous.toFixed(3)}</div>
- </div>
- <div class="result-item">
- <label>峰值转矩 (N·m)</label>
- <div class="result-value">${results.torque.peak.toFixed(3)}</div>
- </div>
- <div class="result-item">
- <label>负载惯量 (kg·m²)</label>
- <div class="result-value">${results.inertia.load.toExponential(3)}</div>
- </div>
- <div class="result-item">
- <label>惯量比</label>
- <div class="result-value">${results.inertia.ratio.toFixed(1)}</div>
- </div>
- <div class="result-item">
- <label>所需功率 (W)</label>
- <div class="result-value">${results.power.required.toFixed(1)}</div>
- </div>
- <div class="result-item">
- <label>额定功率 (W)</label>
- <div class="result-value">${results.power.rated.toFixed(1)}</div>
- </div>
- </div>
- </div>
- `;
- resultsDiv.style.display = 'block';
- }
- clearResults() {
- document.getElementById('results').style.display = 'none';
- }
- resetForm() {
- document.querySelectorAll('input[type="number"]').forEach(input => {
- input.value = input.defaultValue || '';
- input.classList.remove('error');
- });
- this.clearResults();
- this.loadDefaults();
- }
- exportResults() {
- const resultsDiv = document.getElementById('results');
- if (resultsDiv.style.display === 'none') {
- this.showAlert('请先进行计算', 'warning');
- return;
- }
-
- const results = resultsDiv.innerText;
- const blob = new Blob([results], { type: 'text/plain' });
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = `servo_sizing_results_${new Date().toISOString().slice(0, 10)}.txt`;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(url);
- }
- showAlert(message, type = 'info') {
- const alertDiv = document.createElement('div');
- alertDiv.className = `alert alert-${type}`;
- alertDiv.textContent = message;
- document.body.appendChild(alertDiv);
-
- setTimeout(() => {
- alertDiv.remove();
- }, 3000);
- }
- }
- // 初始化应用
- document.addEventListener('DOMContentLoaded', () => {
- new ServoSizer();
- });
|