From caefdefee157ab9b03ce78ea4d485d7606316877 Mon Sep 17 00:00:00 2001 From: Ariella Eliassaf Date: Thu, 29 Sep 2022 21:14:08 +0300 Subject: [PATCH] feat(stepper-motor): add size attribute #138 --- src/stepper-motor-element.stories.ts | 23 +- src/stepper-motor-element.ts | 412 ++++++++++++++++++--------- 2 files changed, 294 insertions(+), 141 deletions(-) diff --git a/src/stepper-motor-element.stories.ts b/src/stepper-motor-element.stories.ts index 01176a1..c513ce9 100644 --- a/src/stepper-motor-element.stories.ts +++ b/src/stepper-motor-element.stories.ts @@ -6,6 +6,7 @@ export default { component: 'wokwi-stepper-motor', argTypes: { angle: { control: { type: 'range', min: 0, max: 360 } }, + size: { control: { type: 'select', options: [8, 11, 14, 17, 23, 34] } }, arrow: { control: { type: 'color' } }, }, args: { @@ -13,25 +14,39 @@ export default { arrow: '', units: '', value: '', + size: 23, }, }; -const Template = ({ angle, arrow, units, value }) => +const Template = ({ angle, arrow, units, value, size }) => html``; export const Default = Template.bind({}); Default.args = {}; export const Rotated90 = Template.bind({}); -Rotated90.args = { angle: 90, units: 'degrees', value: '90' }; +Rotated90.args = { angle: 90, units: 'degrees', value: '90', size: 14 }; export const Steps = Template.bind({}); -Steps.args = { angle: 180, value: '52,500', units: 'steps' }; +Steps.args = { angle: 180, value: '52,500', units: 'steps', size: 14 }; + +export const Degrees = Template.bind({}); +Degrees.args = { angle: 180, value: '180', units: 'degrees', size: 14 }; export const PurpleArrow = Template.bind({}); -PurpleArrow.args = { angle: 70, arrow: '#4a36ba' }; +PurpleArrow.args = { angle: 350, arrow: '#4a36ba', size: 14 }; + +export const Nema17 = Template.bind({}); +Nema17.args = { angle: 70, arrow: '#4a36ba', size: 17 }; + +export const Nema23 = Template.bind({}); +Nema23.args = { angle: 70, arrow: '#4a36ba', value: '1234', units: 'steps', size: 23 }; + +export const Nema34 = Template.bind({}); +Nema34.args = { angle: 70, arrow: '#4a36ba', value: '180', units: 'degrees', size: 34 }; diff --git a/src/stepper-motor-element.ts b/src/stepper-motor-element.ts index 5bc2ac5..50adff3 100644 --- a/src/stepper-motor-element.ts +++ b/src/stepper-motor-element.ts @@ -1,177 +1,315 @@ import { html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin } from '.'; +import { mmToPix } from './utils/units'; + +/** + * NemaSpec describes a NEMA Stepper specification (for the purpose of visualisation) + * + */ +export interface NEMASpec { + id: number; // Nema common number representing the size shorthand (Nema11 Nema 17 etc) + frameSize: number; // the frame size in mm. Since Nema Steppers are square, only one side needed + holeRadius: number; // Fastening hole size + shaftRadius: number; // Motor shaft radius + cornerRadius: number; // Frame corner radius + cornerOffset: number; // Offset from corner to center of hole + bodyRadius: number; // the round motor body size + textSize: number; // Text size showing units etc + /** Y position of value text */ + valueYPosition: number; + /** Y position of units text */ + unitsYPosition: number; +} + +const defaultSize = 23; @customElement('wokwi-stepper-motor') export class StepperMotorElement extends LitElement { - @property() angle = 0; + @property({ type: Number }) angle = 0; @property() arrow = ''; @property() value = ''; @property() units = ''; + @property() size: 8 | 11 | 14 | 17 | 23 | 34 = defaultSize; + + get pinInfo(): ElementPin[] { + const spec = this.nemaSpecMap[this.size] ?? this.nemaSpecMap[defaultSize]; + + // these offsets match the transform in renderFace + const xOff = (spec.frameSize / 2 - 3.75) * mmToPix + 1; + const yOff = (spec.frameSize + 5) * mmToPix; + + const pi = [ + { name: 'A-', y: yOff, x: xOff, number: 1, signals: [] }, + { name: 'A+', y: yOff, x: xOff + 2.54 * mmToPix, number: 2, signals: [] }, + { name: 'B+', y: yOff, x: xOff + 5.08 * mmToPix, number: 3, signals: [] }, + { name: 'B-', y: yOff, x: xOff + 7.62 * mmToPix, number: 4, signals: [] }, + ]; + + return pi; + } - readonly pinInfo: ElementPin[] = [ - { name: 'A+', y: 237, x: 108, number: 1, signals: [] }, - { name: 'A-', y: 237, x: 98, number: 2, signals: [] }, - { name: 'B+', y: 237, x: 117, number: 3, signals: [] }, - { name: 'B-', y: 237, x: 127, number: 4, signals: [] }, - ]; + readonly nemaSpecMap: { [key: string]: NEMASpec } = { + '8': { + id: 8, + frameSize: 20.4, + holeRadius: 0.5, + shaftRadius: 3.5, + cornerRadius: 2.5, + cornerOffset: 2.5, + bodyRadius: 7.7, + textSize: 10, + valueYPosition: 16.5, + unitsYPosition: 19.7, + }, + '11': { + id: 11, + frameSize: 28.2, + holeRadius: 1.25, + shaftRadius: 5, + cornerRadius: 2.5, + cornerOffset: 2.5, + bodyRadius: 11, + textSize: 12, + valueYPosition: 21.5, + unitsYPosition: 24, + }, + '14': { + id: 14, + frameSize: 35.2, + holeRadius: 1.5, + shaftRadius: 5, + cornerRadius: 4.5, + cornerOffset: 4.5, + bodyRadius: 11, + textSize: 14, + valueYPosition: 26, + unitsYPosition: 32, + }, + '17': { + id: 17, + frameSize: 42.3, + holeRadius: 1.5, + shaftRadius: 5, + cornerRadius: 5, + cornerOffset: 5.5, + bodyRadius: 14, + textSize: 16, + valueYPosition: 30.5, + unitsYPosition: 33.7, + }, + '23': { + id: 23, + frameSize: 57.3, + holeRadius: 2.5, + shaftRadius: 6.35, + cornerRadius: 5, + cornerOffset: 5.5, + bodyRadius: 19.5, + textSize: 24, + valueYPosition: 41, + unitsYPosition: 46, + }, + '34': { + id: 34, + frameSize: 86, + holeRadius: 3.25, + shaftRadius: 14, + cornerRadius: 3.25, + cornerOffset: 8.4, + bodyRadius: 36.5, + textSize: 32, + valueYPosition: 68, + unitsYPosition: 75, + }, + }; render() { - const { arrow } = this; - - return html` - - - - - - - - - - - - - - - - - - - + const spec = this.nemaSpecMap[this.size] ?? this.nemaSpecMap[defaultSize]; + + const cornerRadius = spec.cornerRadius; + const holeRadius = spec.holeRadius; + const shaftRadius = spec.shaftRadius; + const frameSize = spec.frameSize; + const cornerOffset = spec.cornerOffset; + const bodyRadius = spec.bodyRadius; + + const halfShaft = shaftRadius / 2; + const halfFrame = frameSize / 2; + + const innerHoleRadius = holeRadius * 0.9; + const outerHoleRadius = holeRadius * 1.1; + + // shaft radius offset, needed for transform + const rOff = Math.sqrt(0.75 * Math.pow(shaftRadius, 2)); + + return html` + + + + + + + + + + + + + + + + + + + + + + + + - + + - + - + - - - - + + + + + + - - - - - - - - - - + + - ${this.units} - ${this.value} - - + ${this.value} + + + ${this.units} + + - - `; + + `; } }