diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json
index 623e7e30..a64b06e8 100644
--- a/libs/core/_locales/core-jsdoc-strings.json
+++ b/libs/core/_locales/core-jsdoc-strings.json
@@ -535,6 +535,7 @@
"pins.pulseIn": "Return the duration of a pulse at a pin in microseconds.",
"pins.pulseIn|param|name": "the pin which measures the pulse, eg: DigitalPin.P0",
"pins.pulseIn|param|value": "the value of the pulse, eg: PulseValue.High",
+ "pins.servoSetContinuous": "Specifies that a continuous servo is connected.",
"pins.servoSetPulse": "Configure the IO pin as an analog/pwm output and set a pulse width. The period is 20 ms period and the pulse width is set based on the value given in **microseconds** or `1/1000` milliseconds.",
"pins.servoSetPulse|param|micros": "pulse duration in micro seconds, eg:1500",
"pins.servoSetPulse|param|name": "pin name",
diff --git a/libs/core/pins.cpp b/libs/core/pins.cpp
index ebf27d11..63b27295 100644
--- a/libs/core/pins.cpp
+++ b/libs/core/pins.cpp
@@ -258,6 +258,14 @@ namespace pins {
PINOP(setServoValue(value));
}
+ /**
+ * Specifies that a continuous servo is connected.
+ */
+ //%
+ void servoSetContinuous(AnalogPin name, bool value) {
+ // handled in simulator
+ }
+
/**
* Configure the IO pin as an analog/pwm output and set a pulse width. The period is 20 ms period and the pulse width is set based on the value given in **microseconds** or `1/1000` milliseconds.
* @param name pin name
diff --git a/libs/core/pinscompat.ts b/libs/core/pinscompat.ts
index 2a728f78..ed29ed21 100644
--- a/libs/core/pinscompat.ts
+++ b/libs/core/pinscompat.ts
@@ -48,6 +48,9 @@ interface PwmOnlyPin extends DigitalInOutPin, AnalogOutPin {
//% parts=microservo trackArgs=0
servoSetPulse(duration: number): void;
+
+ //% parts=microservo tracArgs=0
+ servoSetContinuous(value: boolean): void;
}
//% noRefCounting fixedInstances
@@ -109,6 +112,10 @@ class MicrobitPin implements AnalogInPin, AnalogOutPin, AnalogInOutPin, PwmOnlyP
pins.servoWritePin(this.analogId(), value);
}
+ servoSetContinuous(value: boolean): void {
+ pins.servoSetContinuous(this.analogId(), value);
+ }
+
servoSetPulse(duration: number): void {
pins.servoSetPulse(this.analogId(), duration);
}
diff --git a/libs/core/shims.d.ts b/libs/core/shims.d.ts
index 6f89f2d4..f86d9eb1 100644
--- a/libs/core/shims.d.ts
+++ b/libs/core/shims.d.ts
@@ -732,6 +732,12 @@ declare namespace pins {
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250" shim=pins::servoWritePin
function servoWritePin(name: AnalogPin, value: int32): void;
+ /**
+ * Specifies that a continuous servo is connected.
+ */
+ //% shim=pins::servoSetContinuous
+ function servoSetContinuous(name: AnalogPin, value: boolean): void;
+
/**
* Configure the IO pin as an analog/pwm output and set a pulse width. The period is 20 ms period and the pulse width is set based on the value given in **microseconds** or `1/1000` milliseconds.
* @param name pin name
diff --git a/sim/state/edgeconnector.ts b/sim/state/edgeconnector.ts
index 15a250b7..e32d6c4d 100644
--- a/sim/state/edgeconnector.ts
+++ b/sim/state/edgeconnector.ts
@@ -81,6 +81,13 @@ namespace pxsim.pins {
pin.servoAngle = value;
}
+ export function servoSetContinuous(pinId: number, value: boolean) {
+ let pin = getPin(pinId);
+ if (!pin) return;
+
+ pin.servoSetContinuous(value);
+ }
+
export function servoSetPulse(pinId: number, micros: number) {
let pin = getPin(pinId);
if (!pin) return;
diff --git a/sim/state/edgeconnectorsim.ts b/sim/state/edgeconnectorsim.ts
index 055309de..d4e04a45 100644
--- a/sim/state/edgeconnectorsim.ts
+++ b/sim/state/edgeconnectorsim.ts
@@ -17,6 +17,7 @@ namespace pxsim {
mode = PinFlags.Unused;
pitch = false;
pull = 0; // PullDown
+ servoContinuous = false;
digitalReadPin(): number {
this.mode = PinFlags.Digital | PinFlags.Input;
@@ -59,6 +60,10 @@ namespace pxsim {
runtime.queueDisplayUpdate();
}
+ servoSetContinuous(value: boolean) {
+ this.servoContinuous = !!value;
+ }
+
servoSetPulse(pinId: number, micros: number) {
// TODO
}
diff --git a/sim/state/microservo.ts b/sim/state/microservo.ts
index 5eb54d58..0f9629bd 100644
--- a/sim/state/microservo.ts
+++ b/sim/state/microservo.ts
@@ -10,7 +10,7 @@ namespace pxsim.visuals {
-
+
@@ -24,6 +24,7 @@ namespace pxsim.visuals {
return { el: createMicroServoElement(), x: xy[0], y: xy[1], w: 112.188, h: 299.674 };
}
+ const SPEED = 300; // 0.1s/60 degree
export class MicroServoView implements IBoardPart {
public style: string = "";
public overElement: SVGElement = undefined;
@@ -61,21 +62,36 @@ namespace pxsim.visuals {
translateEl(this.element, [x, y])
}
updateState(): void {
- this.targetAngle = 180.0 - this.state.getPin(this.pin).servoAngle;
- if (this.targetAngle != this.currentAngle) {
+ const p = this.state.getPin(this.pin);
+ const continuous = !!p.servoContinuous;
+ const servoAngle = p.servoAngle;
+ if (continuous) {
+ // for a continuous servo, the angle is interpreted as a rotation speed
+ // 0 -> -100%, 90 - 0%, 180 - 100%
const now = U.now();
- const cx = 56.661;
- const cy = 899.475;
- const speed = 300; // 0.1s/60 degree
const dt = Math.min(now - this.lastAngleTime, 50) / 1000;
- const delta = this.targetAngle - this.currentAngle;
- this.currentAngle += Math.min(Math.abs(delta), speed * dt) * (delta > 0 ? 1 : -1);
- this.crankEl.setAttribute("transform", this.crankTransform
- + ` rotate(${this.currentAngle}, ${cx}, ${cy})`)
- this.lastAngleTime = now;
- setTimeout(() => runtime.updateDisplay(), 20);
+ this.currentAngle = this.targetAngle;
+ this.targetAngle += ((servoAngle - 90) / 90) * SPEED * dt;
+ } else {
+ this.targetAngle = 180.0 - servoAngle;
}
+ if (this.targetAngle != this.currentAngle)
+ this.renderAngle();
}
+
+ private renderAngle() {
+ const now = U.now();
+ const cx = 56.661;
+ const cy = 899.475;
+ const dt = Math.min(now - this.lastAngleTime, 50) / 1000;
+ const delta = this.targetAngle - this.currentAngle;
+ this.currentAngle += Math.min(Math.abs(delta), SPEED * dt) * (delta > 0 ? 1 : -1);
+ this.crankEl.setAttribute("transform", this.crankTransform
+ + ` rotate(${this.currentAngle}, ${cx}, ${cy})`)
+ this.lastAngleTime = now;
+ setTimeout(() => runtime.updateDisplay(), 20);
+ }
+
updateTheme(): void {
}
diff --git a/sim/visuals/microbit.ts b/sim/visuals/microbit.ts
index 1cc064a0..c1c4bd14 100644
--- a/sim/visuals/microbit.ts
+++ b/sim/visuals/microbit.ts
@@ -145,7 +145,7 @@ namespace pxsim.visuals {
}
`;
const BOARD_SVG = `
-