| 1 | // Plotter models, handling modes, and pen-lift motors (port of
|
| 2 | // nextdrawcore/nextdraw_options/models.py).
|
| 3 |
|
| 4 | // Servo PWM limits are in units of 1/12 MHz (~83.3 ns).
|
| 5 | export const zMotors = [
|
| 6 | { motorName: 'Standard servo', pin: 1, max: 27831, min: 9855, sweepTime: 200, moveMin: 45, moveSlope: 2.69 },
|
| 7 | { motorName: 'Narrow-band brushless servo', pin: 2, max: 12600, min: 5400, sweepTime: 70, moveMin: 20, moveSlope: 1.28 },
|
| 8 | ];
|
| 9 |
|
| 10 | // resolution 1: high (2032 steps/in per motor axis), 2: low (1016 steps/in).
|
| 11 | // jerk 0 means constant-speed mode.
|
| 12 | export const handlers = [
|
| 13 | { name: 'No handler selected' },
|
| 14 | { name: 'Technical drawing', resolution: 1, jerk: 20000, speed: 8.6979, speedUp: 8.6979, tolerance: 0.002 },
|
| 15 | { name: 'Handwriting', resolution: 2, jerk: 90000, speed: 7, speedUp: 12, tolerance: 0.008 },
|
| 16 | { name: 'Sketching', resolution: 2, jerk: 14000, speed: 12, speedUp: 12, tolerance: 0.005 },
|
| 17 | { name: 'Constant speed', resolution: 1, jerk: 0, speed: 3.0, speedUp: 8.6979, tolerance: 0.002 },
|
| 18 | ];
|
| 19 |
|
| 20 | function plotter(modelName, travelX, travelY, jerkPenUpHi, jerkPenUpLo, jerkDerate, autoHome, zMotor) {
|
| 21 | return { modelName, travelX, travelY, jerkPenUpHi, jerkPenUpLo, jerkDerate, autoHome, zMotor };
|
| 22 | }
|
| 23 |
|
| 24 | export const plotters = [
|
| 25 | plotter('No model selected', 0, 0, 0, 0, 1, false, 1),
|
| 26 | plotter('AxiDraw V3 or SE/A4', 11.81, 8.58, 19000, 13000, 1.0, false, 0),
|
| 27 | plotter('AxiDraw V3/A3 or SE/A3', 16.93, 11.69, 17000, 12000, 0.9, false, 0),
|
| 28 | plotter('AxiDraw V3 XLX', 23.42, 8.58, 18000, 13000, 1.0, false, 0),
|
| 29 | plotter('AxiDraw MiniKit', 6.30, 4.00, 6000, 6000, 0.6, false, 0),
|
| 30 | plotter('AxiDraw SE/A1', 34.02, 23.39, 13000, 8000, 0.6, false, 0),
|
| 31 | plotter('AxiDraw SE/A2', 23.39, 17.01, 16000, 10000, 0.7, false, 0),
|
| 32 | plotter('AxiDraw V3/B6', 7.48, 5.51, 14000, 14000, 1.0, false, 0),
|
| 33 | plotter('Bantam Tools NextDraw™ 8511', 11.81, 8.58, 19000, 13000, 1.0, true, 1),
|
| 34 | plotter('Bantam Tools NextDraw™ 1117', 16.93, 11.69, 17000, 12000, 0.9, true, 1),
|
| 35 | plotter('Bantam Tools NextDraw™ 2234', 34.02, 23.39, 13000, 8000, 0.6, true, 1),
|
| 36 | ];
|
| 37 |
|
| 38 | const OVERRIDE_KEYS = {
|
| 39 | modelName: 'modelName', travelX: 'travelX', travelY: 'travelY', jerkPenUp: 'jerkPenUp',
|
| 40 | autoHome: 'autoHome', resolution: 'resolution', curveTolerance: 'curveTolerance',
|
| 41 | constSpeed: 'constSpeed', jerkPenDown: 'jerkPenDown', speedLimit: 'speedLimit', zMotor: 'zMotor',
|
| 42 | };
|
| 43 | const SERVO_OVERRIDE_KEYS = ['servoPin', 'servoMax', 'servoMin', 'servoSweepTime', 'servoMoveMin', 'servoMoveSlope'];
|
| 44 |
|
| 45 | /**
|
| 46 | * Apply model-, handling- and servo-specific defaults to nd.params, then any
|
| 47 | * non-null nd.params.overrides (models.apply_model_and_handling).
|
| 48 | */
|
| 49 | export function applyModelAndHandling(nd, initialize = false) {
|
| 50 | const p = nd.params;
|
| 51 | if (initialize) {
|
| 52 | p.modelOld = -1;
|
| 53 | p.handlingOld = -1;
|
| 54 | p.zMotorOld = -1;
|
| 55 | }
|
| 56 | const model = nd.options.model;
|
| 57 | if (model === 0) return;
|
| 58 | if (!(model >= 1 && model < plotters.length)) throw new RangeError(`Invalid model: ${model}`);
|
| 59 |
|
| 60 | if (model !== p.modelOld) {
|
| 61 | p.modelOld = model;
|
| 62 | const m = plotters[model];
|
| 63 | p.modelName = m.modelName;
|
| 64 | p.travelX = m.travelX;
|
| 65 | p.travelY = m.travelY;
|
| 66 | p.jerkDerate = m.jerkDerate;
|
| 67 | p.autoHome = m.autoHome;
|
| 68 | p.zMotor = m.zMotor;
|
| 69 | if (nd.options.penlift === 3) p.zMotor = 1; // Brushless upgrade
|
| 70 | // Handling values depend on the model's jerk derating. (The Python driver
|
| 71 | // keeps the old values until the handling mode changes; we recompute.)
|
| 72 | p.handlingOld = -1;
|
| 73 | }
|
| 74 |
|
| 75 | const handling = nd.options.handling;
|
| 76 | if (handling !== 0 && handling !== p.handlingOld) {
|
| 77 | if (!(handling >= 1 && handling <= 4)) throw new RangeError(`Invalid handling: ${handling}`);
|
| 78 | p.handlingOld = handling;
|
| 79 | const h = handlers[handling];
|
| 80 | p.resolution = h.resolution;
|
| 81 | p.jerkPenDown = h.jerk * p.jerkDerate;
|
| 82 | p.constSpeed = h.jerk === 0;
|
| 83 | p.curveTolerance = h.tolerance;
|
| 84 | const lim = p.resolution === 2 ? p.speedLimXyLr : p.speedLimXyHr;
|
| 85 | p.speedLimit = Math.min(h.speed, lim);
|
| 86 | p.speedUp = Math.min(h.speedUp, lim);
|
| 87 | }
|
| 88 |
|
| 89 | p.jerkPenUp = p.resolution === 2 ? plotters[model].jerkPenUpLo : plotters[model].jerkPenUpHi;
|
| 90 |
|
| 91 | for (const key of Object.keys(OVERRIDE_KEYS)) {
|
| 92 | if (p.overrides[key] != null) p[key] = p.overrides[key];
|
| 93 | }
|
| 94 |
|
| 95 | if (p.zMotor !== p.zMotorOld) {
|
| 96 | p.zMotorOld = p.zMotor;
|
| 97 | const z = zMotors[p.zMotor];
|
| 98 | p.servoPin = z.pin;
|
| 99 | p.servoMax = z.max;
|
| 100 | p.servoMin = z.min;
|
| 101 | p.servoSweepTime = z.sweepTime;
|
| 102 | p.servoMoveMin = z.moveMin;
|
| 103 | p.servoMoveSlope = z.moveSlope;
|
| 104 | }
|
| 105 | for (const key of SERVO_OVERRIDE_KEYS) {
|
| 106 | if (p.overrides[key] != null) p[key] = p.overrides[key];
|
| 107 | }
|
| 108 | }
|