-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeneralmech.html
732 lines (669 loc) · 30 KB
/
generalmech.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
<!DOCTYPE html>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<link rel="stylesheet" href="include/style.css">
<!-- Include relevant libraries -->
<script type="text/javascript" src="js/eclib.js"></script>
<script type="text/javascript" src="js/units.js"></script>
<script type="text/javascript" src="js/export.js"></script>
<script type="text/javascript" src="js/motors.js"></script>
<script type="text/javascript" src="js/plots.js"></script>
<script type="text/javascript" src="js/walkthrough.js"></script>
<!-- Export library requires this script tag -->
<script id="EXP_inputs_frame" ></script>
<script type="text/javascript" id="main">
EXP_FN_BASE = 'simplemech'; // filename base for export utility
UNIT_MAP = { // map of units
"torque": ["N-m", "N-m"],
"encoder_cpx": ["c/m", "c/ft"],
"radius": ["mm","in"],
"force": ["N", "lbf"],
"mass": ["kg", "lbm"],
"speed": ["m/s", "ft/s"],
"distance": ["m", "ft"],
"acceleration": ["m/s^2", "ft/s^2"],
'moi': ['kg mm^2', 'lbm in^2'],
"omega": ["RPM", "RPM"],
"theta": ["rev", "rev"],
"alpha": ["RPM/s", "RPM/s"],
"angle": ["deg", "deg"],
"pct": ["%", "%"]
};
WALK_STEPS = [{
poi: 'user_input_motor',
desc: 'Input details about the motors powering your mechanism...',
valign: 'bottom'
},{
poi: 'user_input_gratio',
desc: 'Input the gear ratio (you can use the dropdown to compute it)...'
},{
poi: 'user_input_encoder',
desc: 'The encoder box can be used to help figure out encoder resolution...'
},{
poi: 'user_input_traction',
desc: 'Traction limiting should be used for drivetrains...'
},{
poi: 'user_input_electrical',
desc: 'Simultion of voltage drop and current limiting can be done...'
},{
poi: 'user_input_radius',
desc: "Plug in the effective radius of your mechanism (arm length, wheel radius, or spool radius)..."
},{
poi: 'user_input_mass',
desc: 'Plug in the mass of the system being accelerated...'
},{
poi: 'user_input_load',
desc: 'Plug in the load perpindicular to the radius...'
},{
poi: 'user_input_endcond',
desc: 'Plug in an end condition for simulation...'
},{
poi: 'computed_outputs',
desc: 'Computed/simulated values will appear here.'
},{
poi: 'chart',
desc: 'Simulation results are plotted here.'
},{
poi: 'chart',
desc: 'Click on the plot to probe points for values.'
},{
poi: 'toggle_tips_label',
desc: 'More tips and notes are in here.'
},{
poi: 'toggle_varref_label',
desc: 'Variables that can be used in the load and end condition expressions are here.'
}];
</script>
<script type="text/javascript">
/* Initialization routine run on page load */
function init() {
EC_onload();
MOTOR_setupMotorSelect("motor");
EXP_onload();
MOTOR_selectMotor("motor");
UNIT_change();
// on keyup for all variables
EC_setOnInput(function(e) {
let key = e.keyCode ? e.keyCode : e.which;
let input = e.target;
if(input.id == 'toggle-gratio'){
collapseGearRatio();
calcRatio();
compute();
}
if(input.id.startsWith('toggle')) return; // ignore these, just css stuff
// if a key is pressed, invalidate current results
setError(1);
// if a gear ratio element was edited, compute gear ratio
if (input.id.startsWith("G") && input.id.length == 3) {
calcRatio();
}
if (input.type == 'checkbox') {
compute();
}
});
EC_setOnKeyUp(); // default handler is OK
calcRatio();
compute();
WALK_onload();
}
let g = 9.81; // acceleration due to gravity
function compute() {
let computed_basic = false;
try{
let dt = 0;
let dt_override = getV("dt_override", undefined);
let r = getV("radius");
let m = getV("mass");
let G = getV("G");
let motor = MOTOR_packMotor('motor');
let mu = +Infinity;
let N = +Infinity;
let cur_limit = NaN;
let batt_voltage = 1;
let motor_voltage = 1;
let resistance = 0;
if (document.getElementById("enable_friction").checked) {
mu = getV("friction_mu", 0);
N = m*g*getV("friction_pctloaded",100)/100;
}
simulate_electrical = document.getElementById("enable_electrical_sys").checked;
if (simulate_electrical) {
motor = MOTOR_packElectricalMotor('motor');
}
let load_expr = document.getElementById("load").value;
let end_expr = document.getElementById("endcond").value;
if(end_expr == "") end_expr = "0";
I = m*r*r;
// computing basic parameters
// variables object to pass into parseMath
let variables = {
t : 0,
omega : 0,
theta : 0,
omega_m : 0,
theta_m : 0,
x : 0,
v : 0
}
let Mres = convertFrom(parseMath(load_expr, variables), UNIT_MAP.force[UNIT_sys])*r;
let run_state = MOTOR_computeState(motor, 'torque', 0);
setV("theor_run_spd", run_state.speed*r/G);
setV("theor_run_current", run_state.current);
let free_state = MOTOR_computeState(motor, 'torque', 0);
setV("theor_free_spd", free_state.speed*r/G);
setV("theor_free_current", free_state.current);
setV("theor_adj_spd", free_state.speed*r/G*getV("gearbox_speedloss", NaN));
let stall_state = MOTOR_computeState(motor, 'speed', 0);
setV("theor_stall_force", stall_state.torque*G/r);
setV("theor_stall_current", stall_state.current);
if (isFinite(mu*N*r/G)) {
let traction_state = MOTOR_computeState(motor, 'torque', mu*N*r/G);
setV("theor_traction_force", traction_state.torque*G/r);
setV("theor_traction_current", traction_state.current);
} else {
setV("theor_traction_force", '-');
setV("theor_traction_current", '-');
}
// encoder computations
enc_plc = document.getElementById('encoder_placement').value;
enc_els = document.getElementsByClassName('encoder_detail');
if (enc_plc == 'none') {
for (i=0;i<enc_els.length;i++) {
enc_els[i].style.display = 'none';
}
} else {
for (i=0;i<enc_els.length;i++) {
enc_els[i].style.display = 'table-row';
}
cpx = getV('encoder_cpr')/NaNTo(1,getV('encoder_reduction'))/(r*2*Math.PI);
if(enc_plc == 'motor') cpx *= G;
setV('encoder_cpx', cpx);
setV('encoder_max_cps', cpx*r*motor.max_speed/G);
}
computed_basic = true;
cur_cons = 0;
alpha_o = NaN;
alpha_ar = [0,0];
omega_ar = [0,0];
theta_ar = [0];
t_ar = [0];
channels = {t:[],v:[],d:[],cur:[],f:[],a:[],omega:[],theta:[],T:[],alpha:[],voltage:[]}; // plotting channels
i=0;
while(1) {
// make variables for call to parseMath
variables.t = t_ar[t_ar.length-1];
variables.omega = convertTo(omega_ar[omega_ar.length-1], UNIT_MAP.omega[UNIT_sys]);
variables.theta = convertTo(theta_ar[theta_ar.length-1], UNIT_MAP.theta[UNIT_sys]);
variables.omega_m = convertTo(omega_ar[omega_ar.length-1]*G, UNIT_MAP.omega[UNIT_sys]);
variables.theta_m = convertTo(theta_ar[theta_ar.length-1]*G, UNIT_MAP.theta[UNIT_sys]);
variables.v = convertTo(omega_ar[omega_ar.length-1]*r, UNIT_MAP.speed[UNIT_sys]);
variables.x = convertTo(theta_ar[theta_ar.length-1]*r, UNIT_MAP.distance[UNIT_sys]);
// check if end condition has been met
if (i > 5000 || parseMath(end_expr, variables)) break;
let motor_state = MOTOR_computeState(motor, 'speed', omega_ar[omega_ar.length-1]*G);
if (motor_state.torque*G > N*mu*r){
motor_state = MOTOR_computeState(motor, 'torque', N*mu*r/G);
}
let T = motor_state.torque*G;
//console.log(motor_state);
Mres = convertFrom(parseMath(load_expr, variables), UNIT_MAP.force[UNIT_sys])*r;
alpha = (motor_state.torque*G-Mres) / I;
if(isNaN(alpha_o)) alpha_o = alpha;
alpha_ar.push(alpha);
// Use Adams-Bradforth method of integration
theta_ar.push(theta_ar[theta_ar.length-1]
+ omega_ar[omega_ar.length-1]*dt*3/2
- omega_ar[omega_ar.length-2]*dt*1/2);
omega_ar.push(omega_ar[omega_ar.length-1]
+ alpha_ar[alpha_ar.length-1]*dt*3/2
- alpha_ar[alpha_ar.length-2]*dt*1/2);
t_ar.push(t_ar[t_ar.length-1]+dt);
// plain euler integration is OK for current
cur = motor_state.current;
cur_cons = cur_cons + dt*cur;
// push to channels for plotting
channels.t.push(t_ar[t_ar.length-1]);
channels.cur.push(cur);
channels.v.push(omega_ar[omega_ar.length-1]*r);
channels.d.push(theta_ar[theta_ar.length-1]*r);
channels.f.push(T/r);
channels.a.push(alpha*r);
channels.omega.push(omega_ar[omega_ar.length-1]);
channels.theta.push(theta_ar[theta_ar.length-1]);
channels.T.push(T);
channels.alpha.push(alpha);
channels.voltage.push(motor_state.voltage);
if (dt_override)
dt = dt_override;
else
dt = Math.min(0.1,Math.max(1e-7,Math.min(Math.abs(motor.max_speed/G/alpha_o),Math.abs(motor.max_speed/G/alpha))/40));
i++;
}
omega_ar.shift(); //remove the first element of this array that was there for adams-bradforth
// draw the line plot
PLOT_drawLinePlot({
chartName: "chart",
axes: {
x: {
numTicks: 10,
boxEnds: false,
negativeHandling: 'posonly',
margin: 15
}, y: {
numTicks: 7,
boxEnds: true,
negativeHandling: 'posonly',
margin: 5
}, z: {
syncWithY: true,
margin: 5
}
},
datasets: {
t: {axis: 'x'},
d: {axis: 'y'},
v: {axis: 'y'},
cur: {axis: 'z'},
f: {axis: 'z'}
},
queries: {
INDEX: {},
cur: {},
t: {},
d: {},
v: {},
a: {},
f: {},
omega: {},
theta: {},
T: {},
alpha: {},
voltage: {}
}
}, channels);
setV("endcond_met", parseMath(end_expr, variables) ? t_ar[t_ar.length-1]:"NOT MET");
setV("current_cons", cur_cons);
}catch(err){
console.log(err);
if (computed_basic)
setError(2, "Finished basic computations, but simulation failed. Most likely, you didn't plug in a mass value (simulation doesn't work without it). Error Code: " + err);
else
setError(2, err);
return;
}
setError(0);
EXP_dumpPersistence();
}
/* compute gear ratio from expanded sheet */
function calcRatio() {
var G = 1;
G *= getV("G1B",1);
G *= getV("G2B",1);
G *= getV("G3B",1);
G *= getV("G4B",1);
G /= getV("G1A",1);
G /= getV("G2A",1);
G /= getV("G3A",1);
G /= getV("G4A",1);
setV("G", G);
}
/* show/hide the gear ratio calculator */
function collapseGearRatio() {
let open = document.getElementById('toggle-gratio').checked;
document.getElementById('G').readOnly = open;
if(open) calcRatio();
}
</script>
<html>
<!-- Make sure to call your init function on document load -->
<!-- You can copy the topbar template here -->
<body onload="init()">
<div id="topbar">
<div class="topbar-la selectable" onclick="window.location='./'">EveryCalc</div>
<div class="topbar-la" id='topbar_version'></div>
<div class="topbar-la" id='topbar_filename'></div>
<div class="topbar-la" id='topbar_unit'>
<!-- Required for unit library. You could also put this in the calculator main body -->
<select id="unit_select" onchange="UNIT_change(); compute();">
<option value=0 >Metric</option>
<option value=1 selected="selected">English</option>
</select>
</div>
<div class="topbar-ctr" id="topbar_title">General Mechanism Calc</div>
<div class="topbar-ra selectable" id="topbar_status" onclick="compute();"><span></span><span class='ttt'></span></div>
<div class="topbar-ra selectable" onclick="downloadPage();" id="download">Export HTML</div>
<div class="topbar-ra selectable" onclick="printPage();">Print</div>
<div class="topbar-ra selectable" onclick="WALK_enable();">Tutorial</div>
<a id="download_frame" hidden></a>
</div>
<svg id="walkthrough_overlay" onclick="WALK_nextStep()" >
<path id="walkthrough_frame" ></path>
<text id="walkthrough_text" ></text>
<text id="walkthrough_skip_button" onclick="WALK_disable();">Skip Tutorial</text>
</svg>
<!-- From here go nuts, do whatever works for you. Use the container to keep stuff from spilling under topbar. I'll point out patterns to pay attention to. -->
<div style="float: left; display:table-cell;" class="container">
<div class="even" id="user_input_motor">
<table>
<tr>
<th colspan=6 style="text-align: center;" class="rowlabel bold">Gearbox</th>
</tr><tr>
<td class="rowlabel"># Motors<span class="ttt">How many motors do you have in total for this mechanism (assuming they're identical, and geared together)</span></td>
<td><input class='narrow' id="motor_count" oninput="MOTOR_selectMotor('motor'); compute();" value=1 /></td>
<td></td>
</tr><tr>
<td class="rowlabel">Efficiency<span class="ttt">Efficiency of the transmission</span></td>
<td><input class='narrow' data-unit="pct" id="motor_efficiency" oninput="MOTOR_selectMotor('motor'); compute();" value=85 /></td>
<td class="unit" data-unit="pct" ></td>
<td class="rowlabel">Speed Loss<span class="ttt">Magical "Speed Loss Constant" from the JVN-calcs. Doesn't impact simulation, only used to compute "JVN adjusted speed".</span></td>
<td><input class='narrow' data-unit="pct" id="gearbox_speedloss" oninput="compute()" value=80 /></td>
<td class="unit" data-unit="pct" ></td>
</tr>
</table>
<span class="rowlabel">Motor</span>
<select class="doublewide" id="motor_select" onchange="MOTOR_selectMotor('motor'); compute();">
</select>
<input class="dropdown" type="checkbox" id="toggle-motor">
<label class="dropdown" for="toggle-motor">V</label>
<table id='detail_motor' class="dropdown">
<tr>
<th class="rowlabel">Free Speed<span class="ttt">The maximum RPM of the motor</span></th>
<td><input data-unit="omega" id="motor_max_speed" readonly value=5880 /></td>
<td class="unit" data-unit="omega" >[RPM]</td>
</tr><tr>
<th class="rowlabel">Stall Torque<span class="ttt">The maximum torque of the motor, occurring at 0 RPM</span></th>
<td><input data-unit="torque" id="motor_stall_torque" readonly value=3.36 /></td>
<td class="unit" data-unit="torque" id="unit_motor_stall_torque"></td>
</tr><tr>
<th class="rowlabel">Free Current<span class="ttt">The current drawn when the motor is unloaded</span></th>
<td><input id="motor_free_current" readonly value=1.3 /></td>
<td class="unit">[A]</td>
</tr><tr>
<th class="rowlabel">Stall Current<span class="ttt">The current drawn at 0 RPM / Max Torque</span></th>
<td><input id="motor_stall_current" readonly value=166 /></td>
<td class="unit">[A]</td>
</tr>
</table>
</div>
<div class="odd" id="user_input_gratio">
<span class='rowlabel bold'>Gear Ratio<span class="ttt">The overall gear ratio. Larger than 1 is a reduction, smaller is a RPM increase. Empty cells are assumed to be 1. You can either blank out all the cells, and plug in a number in the top right one, or build a ratio by typing in the number of teeth on each gear (or belts/sprockets) starting from the motor.</span></span>
<input id="G"/>
<input class="dropdown" type="checkbox" id="toggle-gratio">
<label class="dropdown" for="toggle-gratio">V</label>
<table id='detail_gratio' class="dropdown">
<tr>
<td><input id="G1A" value=12 /></td>
<td class="tiny">:</td>
<td><input id="G1B" value=72 /></td>
</tr><tr>
<td><input id="G2A" /></td>
<td class="tiny">:</td>
<td><input id="G2B" /></td>
</tr><tr>
<td><input id="G3A" /></td>
<td class="tiny">:</td>
<td><input id="G3B" /></td>
</tr><tr>
<td><input id="G4A" /></td>
<td class="tiny">:</td>
<td><input id="G4B" /></td>
</tr>
</table>
</div>
<div class="even" id="user_input_encoder">
<span class="rowlabel bold">Encoder<span class="ttt">(Optional) Where is the encoder placed - on (or in) the motor, or on the output shaft?</span></span>
<select id="encoder_placement" onchange="compute()" class="doublewide">
<option value="none">No Encoder</option>
<option value="motor">To Motor</option>
<option value="output">To Output</option>
</select>
<input class="dropdown" type="checkbox" id="toggle_encoder">
<label class="dropdown" for="toggle_encoder">V</label>
<table id='detail_encoder' class="dropdown">
<tr class='encoder_detail'>
<th class="rowlabel">CPR<span class="ttt">Encoder Counts Per Revolution<br/>(you can also put ticks, and ticks will be computed. Math is the same)</span></th>
<td><input id="encoder_cpr" onchange="compute()" value=1 /></td>
<th class="rowlabel">C/x<span class="ttt">Encoder Counts Per Distance Traveled<br/>(how many encoder counts per unit distance traveled)</span></th>
<td><input data-unit="unit_encoder_cpx" id="encoder_cpx" value=1 readonly /></td>
<td class="unit" data-unit="unit_encoder_cpx"></td>
</tr><tr class='encoder_detail'>
<th class="rowlabel">Reduction<span class="ttt">Additional reduction applied between the shaft and the encoder</span></th>
<td><input id="encoder_reduction" onchange="compute()" value='' /></td>
<th class="rowlabel">Max CPS<span class="ttt">Maximum Counts per Second, at free speed</span></th>
<td><input id="encoder_max_cps" value=1 readonly /></td>
</tr>
</table>
</div>
<div class="odd" id="user_input_traction">
<input class="dropdown" type="checkbox" id="enable_friction" onclick="compute();" >
<label class="dropdown" for="enable_friction">Enable Traction Limiting</label>
<table id='detail_friction' style='display:none;'>
<tr>
<th class="rowlabel">% Mass Powered<span class="ttt">How much of the mass being accelerated is on powered axles?<br/>You could also use this to deal with hill climbing.</span></th>
<td><input id="friction_pctloaded" value=100 /></td>
<td class="unit" >[%]</td>
</tr><tr>
<th class="rowlabel">Friction Coefficient</th>
<td><input id="friction_mu"/></td>
<td class="unit">[-]</td>
</tr>
</table>
</div>
<div class="even" id="user_input_electrical">
<input class="dropdown" type="checkbox" id="enable_electrical_sys" onclick="compute();" >
<label class="dropdown" for="enable_electrical_sys">Enable Electrical Simulation</label>
<table id='detail_electrical' style='display:none;'>
<tr>
<th class="rowlabel">Current Limit<span class="ttt">Impose a current limit? Applies to the sum of all motor inputs. Leave empty to disable.</span></th>
<td><input id="motor_current_limit" value=100 /></td>
<td class="unit" >[A]</td>
</tr><tr>
<th class="rowlabel">Battery Voltage<span class="ttt">Nominal battery voltage / Motor nominal voltage</span></th>
<td><input id="motor_battery_voltage" value=12 class="narrow" /> / <input id="motor_voltage" value=12 class="narrow" /></td>
<td class="unit" >[V]</td>
</tr><tr>
<th class="rowlabel">System Resistance<span class="ttt">Battery internal resistance + wire resistance</span></th>
<td><input id="motor_wire_resistance" value=100 /></td>
<td class="unit" >[Ohms]</td>
</tr>
</table>
</div>
<div class="odd">
<table>
<tr><th colspan=6 style="text-align: center;" class="rowlabel bold">Interface</th></tr>
<tr id="user_input_radius">
<th class="rowlabel">Radius <span class="ttt">Radius of the output.<br/>If this is an arm, input the length of the arm.<br/>If this is an elevator, input the radius of the spool.<br/>If this is a drivetrain, input the radius of the wheel.</span></th>
<td><input data-unit="radius" id="radius" oninput="" value=2 /></td>
<td class="unit" data-unit="radius" id="unit_radius"></td>
</tr><tr id="user_input_mass">
<th class="rowlabel">Mass<span class="ttt">[Equivalent] Mass.<br/>If you're running a linear device, just put its mass in here.<br/>If you are analyzing a rotational device, put the moment of inertia, divided by the radius squared here.</span></th>
<td><input data-unit="mass" id="mass" oninput="" value=30 /></td>
<td class="unit" data-unit="mass" id="unit_mass"></td>
</tr><tr id="user_input_load">
<th class="rowlabel">Load<span class="ttt">(Optional) Load.</span></th>
<td><input data-unit="force" id="load" oninput="" /></td>
<td class="unit" data-unit="force" id="unit_load"></td>
</tr><tr>
<th class="rowlabel">Override dt=<span class="ttt">(Optional) Timestep override. Default is to auto-time-step. This doesn't work well for mechanisms that are extremely quick.</span></th>
<td><input id="dt_override" value=""/></td>
<td class="unit">[s]</td>
</tr><tr id="user_input_endcond">
<th class="rowlabel">End Condition<span class="ttt">(Optional) End condition. Must be an expression that logically evaluates.<br/>You can use any javascript operators/comparators (+,-,*,/,>,<,Math.sin(...),...).<br/>You can use any variables described in the pullout below.</span></th>
<td colspan=2><input id="endcond" value="x > 5" class="doublewide"/></td>
</tr>
</table>
</div>
<div class="output" id="computed_outputs">
<table>
<tr><th colspan=5 style="text-align: center;" class="bold">Basic Calculations</th></tr>
<tr>
<th class="rowlabel">JVN Adjusted Speed<span class="ttt">Adjusted speed; computed like in the JVN calc.</span></th>
<td><input data-unit="speed" id="theor_adj_spd" readonly /></td>
<td class="unit" data-unit="speed" id="unit_theor_adj_spd"></td>
</tr><tr>
<th class="rowlabel">No Load<span class="ttt">Speed without any load on the system.<br/>Equivalent to the JVN calc.</span></th>
<td><input data-unit="speed" id="theor_free_spd" readonly /></td>
<td class="unit" data-unit="speed" id="unit_theor_free_spd"></td>
<td><input id="theor_free_current" readonly /></td>
<td class="unit">[A]</td>
</tr><tr>
<th class="rowlabel">Running<span class="ttt">Speed and current while running at steady-state, ASSUMING THAT ALL TRANSIENT VARIABLES (v,x,omega,theta) ARE ZERO.<br/>Equivalent to the JVN calc.</span></th>
<td><input data-unit="speed" id="theor_run_spd" readonly /></td>
<td class="unit" data-unit="speed" ></td>
<td><input id="theor_run_current" readonly /></td>
<td class="unit">[A]</td>
</tr><tr>
<th class="rowlabel">Stall<span class="ttt">Force produced while at stall (ignoring external load/mass)<br/>Equivalent to the JVN calc.</span></th>
<td><input data-unit="force" id="theor_stall_force" readonly /></td>
<td class="unit" data-unit="force" id="unit_theor_stall_force"></td>
<td><input id="theor_stall_current" readonly /></td>
<td class="unit">[A]</td>
</tr><tr id="theor_traction_force_row">
<th class="rowlabel">Traction Limit</th>
<td><input data-unit="force" id="theor_traction_force" readonly /></td>
<td class="unit" data-unit="force"></td>
<td><input id="theor_traction_current" readonly /></td>
<td class="unit">[A]</td>
</tr>
<tr><th colspan=5 style="text-align: center;" class="bold">Simulation Results</th></tr>
<tr>
<th class="rowlabel">Time To End<span class="ttt">When simulation terminated if the end condition was met. If not, it will tell you the end condition was unmet. Auto-time-stepping may cause runs with high initial accelerations to have very short runtimes.</span></th>
<td><input id="endcond_met" readonly /></td>
<td class="unit">[s]</td>
</tr><tr>
<th class="rowlabel">Current Used<span class="ttt">Total electrical consumption in the simulation period</span></th>
<td><input id="current_cons" readonly /></td>
<td class="unit">[A-s]</td>
</tr>
</table>
</div>
<div class="even">
<input class="dropdown" type="checkbox" id="toggle_tips">
<label class="dropdown" for="toggle_tips" id="toggle_tips_label">Show Tips</label>
<div class="dropdown">
<p>The calculator can be used for any mechanism. For a drivetrain, plug in wheel radius, robot mass, and nothing for load (unless you're pushing something). For an arm, plug in the radius to the center of mass, arm's mass, and the effective load at the center of gravity. For an elevator, plug in pulley radius, elevator mass, and the elevator load (weight minus any counterbalancing). Reverse the load to go 'down'.</p>
<p>Click on the chart to probe points!</p>
<p>The gear ratio has a dropdown that can be used to compute ratios from gearsets. Otherwise you can collapse it and plug in a gear ratio directly.</p>
<p>The simulator uses auto-time-stepping based on the initial acceleration. It's best to specify an end condition. If your mechanism is extremely snappy, it's probably geared really, really low- so it will put the motor near free speed, which is generally undesirable.</p>
<p>You can input arithmetic anywhere. But only input symbolic math (with variables) in the end condition and load equation boxes.</p>
</div>
</div>
<div class="odd" >
<input class="dropdown" type="checkbox" id="toggle_varref">
<label class="dropdown" for="toggle_varref" id="toggle_varref_label">Show Variable Reference</label>
<table class="dropdown">
<tr><th class='rowlabel'>G</th><td class="unit">[-]</td><td>Overall gear ratio</td></tr>
<tr><th class='rowlabel'>m</th><td class="unit" data-unit="mass">[kg]</td><td>Mass</td></tr>
<tr><th class='rowlabel'>I</th><td class="unit" data-unit="moi"></td><td>MOI</td></tr>
<tr><th class='rowlabel'>r</th><td class="unit" data-unit="radius"></td><td>Radius</td></tr>
<tr><th class='rowlabel'>t</th><td class="unit">[s]</td><td>Time</td></tr>
<tr><th class='rowlabel'>v</th><td class="unit" data-unit="speed"></td><td>Lin. Velocity</td></tr>
<tr><th class='rowlabel'>x</th><td class="unit" data-unit="distance"></td><td>Lin. Position</td></tr>
<tr><th class='rowlabel'>omega</th><td class="unit" data-unit="omega"></td><td>Rot. Velocity</td></tr>
<tr><th class='rowlabel'>theta</th><td class="unit" data-unit="theta"></td><td>Rot. Position</td></tr>
<tr><th class='rowlabel'>omega_m</th><td class="unit" data-unit="omega"></td><td>Rot. Motor Velocity</td></tr>
<tr><th class='rowlabel'>theta_m</th><td class="unit" data-unit="theta"></td><td>Rot. Motor Position</td></tr>
</table>
</div>
</div>
</div>
<div style="margin-left: 0px; display:table-cell;" class="container" id="charts">
<svg version="1.2" class="plot" id='chart' aria-labelledby="title" role="img" style="height:550px; width:800px;">
<rect class="plot-background" id="chart_background" x=90 y=20 width=615 height=430 />
<g>
<line class="plot-axis" id="chart_x_axis" x1=90 x2=705 y1=450 y2=450></line>
<line class="plot-axis" id="chart_y_axis" x1=90 x2=90 y1=20 y2=450></line>
<line class="plot-axis" id="chart_z_axis" x1=705 x2=705 y1=20 y2=450></line>
</g>
<g class="plot-grid" id="chart_x_grid"></g>
<g class="plot-grid" id="chart_y_grid"></g>
<g class="plot-grid" id="chart_z_grid"></g>
<g class="plot-labels">
<text x="375" y=485 class="plot-titlelabel">Time [s]</text>
<text x=-300 y=15 class="plot-titlelabel unit" transform="rotate(270)" id="chart_d_label" data-unit="distance" fill="#0074d9">Position []</text>
<text x=-180 y=15 class="plot-titlelabel unit" transform="rotate(270)" id="chart_v_label" data-unit="speed" fill="#d91200">Velocity []</text>
<text x=-240 y=15 class="plot-titlelabel" transform="rotate(270)" fill="#111">/</text>
<text x=-300 y=800 class="plot-titlelabel" transform="rotate(270)" fill="#444">Current [A]</text>
<text x=-180 y=800 class="plot-titlelabel unit" transform="rotate(270)" id="chart_f_label" data-unit="force" fill="#c48900">Force []</text>
<text x=-240 y=800 class="plot-titlelabel" transform="rotate(270)" fill="#111">/</text>
</g>
<g class="plot-axlabels" id='chart_x_axlabels'></g>
<g class="plot-axlabels" id='chart_z_axlabels'></g>
<g class="plot-axlabels" id='chart_y_axlabels'></g>
<g>
<line class="plot-querybar" id="chart_querybar" x1=100 x2=100 y1=15 y2=455 opacity=0></line>
</g>
<polyline
id='chart_d_line'
fill='none'
stroke='#0074d9'
stroke-width=2
points="
"/>
<polyline
id='chart_v_line'
fill='none'
stroke='#d91200'
stroke-width=2
points="
"/>
<polyline
id='chart_cur_line'
fill='none'
stroke='#444'
stroke-width=2
points="
"/>
<polyline
id='chart_f_line'
fill='none'
stroke='#c48900'
stroke-width=2
points="
"/>
</svg>
<div class="output-plot" id='chart_querytable' style='display:none;'>
<table>
<tr>
<th class="rowlabel">Queried Time<span class="ttt">Query a time on the graph by clicking (and optionally dragging) a point. Timepoint represented by a vertical bar.</span></th>
<td><input id="chart_t" readonly /></td>
<td class="unit">[s]</td>
<td><input id="chart_INDEX" readonly /></td>
<td class="unit">iterations</td>
</tr><tr>
<th class="rowlabel">Electrical</th>
<td><input id="chart_cur" readonly /></td>
<td class="unit">[A]</td>
<td><input id="chart_voltage" readonly /></td>
<td class="unit">[V]</td>
</tr><tr>
<th class="rowlabel">Position</th>
<td><input data-unit="distance" id="chart_d" readonly /></td>
<td class="unit" data-unit="distance" id="unit_chart_d"></td>
<td><input data-unit="theta" id="chart_theta" readonly /></td>
<td class="unit" data-unit="theta" id="unit_chart_theta"></td>
</tr><tr>
<th class="rowlabel">Velocity</th>
<td><input data-unit="speed" id="chart_v" readonly /></td>
<td class="unit" data-unit="speed" id="unit_chart_v"></td>
<td><input data-unit="omega" id="chart_omega" readonly /></td>
<td class="unit" data-unit="omega" id="unit_chart_omega"></td>
</tr><tr>
<th class="rowlabel">Acceleration</th>
<td><input data-unit="acceleration" id="chart_a" readonly /></td>
<td class="unit" data-unit="acceleration" id="unit_chart_a"></td>
<td><input data-unit="alpha" id="chart_alpha" readonly /></td>
<td class="unit" data-unit="alpha" id="unit_chart_alpha"></td>
</tr><tr>
<th class="rowlabel">Actuator Force<span class="ttt">The force the actuator puts out. THIS IS NOT NET FORCE. Subtract off load equation to find net force.</span></th>
<td><input data-unit="force" id="chart_f" readonly /></td>
<td class="unit" data-unit="force" id="unit_chart_f"></td>
<td><input data-unit="torque" id="chart_T" readonly /></td>
<td class="unit" data-unit="torque" id="unit_chart_T"></td>
</tr>
</table>
</div>
</div>
</body>
</html>