diff --git a/libs/color-sensor/_locales/color-sensor-jsdoc-strings.json b/libs/color-sensor/_locales/color-sensor-jsdoc-strings.json index bcd25d8f..3b3ab874 100644 --- a/libs/color-sensor/_locales/color-sensor-jsdoc-strings.json +++ b/libs/color-sensor/_locales/color-sensor-jsdoc-strings.json @@ -1,10 +1,12 @@ { "sensors.ColorSensor": "The color sensor is a digital sensor that can detect the color or intensity\nof light that enters the small window on the face of the sensor.", - "sensors.ColorSensor.ambientLight": "Measures the ambient light value from 0 (darkest) to 100 (brightest).", "sensors.ColorSensor.color": "Get the current color from the color sensor.", "sensors.ColorSensor.colorMode": "Gets the current color mode", + "sensors.ColorSensor.light": "Measures the ambient or reflected light value from 0 (darkest) to 100 (brightest).", "sensors.ColorSensor.onColorDetected": "Registers code to run when the given color is detected.", "sensors.ColorSensor.onColorDetected|param|color": "the color to detect, eg: ColorSensorColor.Blue", "sensors.ColorSensor.onColorDetected|param|handler": "the code to run when detected", - "sensors.ColorSensor.reflectedLight": "Measures the reflected light value from 0 (darkest) to 100 (brightest)." + "sensors.ColorSensor.onLightChanged": "Registers code to run when the ambient light changes.", + "sensors.ColorSensor.onLightChanged|param|condition": "the light condition", + "sensors.ColorSensor.onLightChanged|param|handler": "the code to run when detected" } \ No newline at end of file diff --git a/libs/color-sensor/_locales/color-sensor-strings.json b/libs/color-sensor/_locales/color-sensor-strings.json index a74db2d9..3211eddc 100644 --- a/libs/color-sensor/_locales/color-sensor-strings.json +++ b/libs/color-sensor/_locales/color-sensor-strings.json @@ -10,10 +10,13 @@ "ColorSensorMode.AmbientLightIntensity|block": "ambient light intensity", "ColorSensorMode.Color|block": "color", "ColorSensorMode.ReflectedLightIntensity|block": "reflected light intensity", - "sensors.ColorSensor.ambientLight|block": "`icons.colorSensor` %color| ambient light", + "LightCondition.Dark|block": "dark", + "LightIntensityMode.Ambient|block": "ambient light", + "LightIntensityMode.Reflected|block": "reflected light", "sensors.ColorSensor.color|block": "`icons.colorSensor` %color| color", + "sensors.ColorSensor.light|block": "`icons.colorSensor` %color|%mode", "sensors.ColorSensor.onColorDetected|block": "on `icons.colorSensor` %sensor|detected color %color", - "sensors.ColorSensor.reflectedLight|block": "`icons.colorSensor` %color| reflected light", + "sensors.ColorSensor.onLightChanged|block": "on `icons.colorSensor` %sensor|%mode|%condition", "sensors.colorSensor1|block": "1", "sensors.colorSensor2|block": "2", "sensors.colorSensor3|block": "3", diff --git a/libs/color-sensor/color.ts b/libs/color-sensor/color.ts index 8f4b143c..c6f0bdb5 100644 --- a/libs/color-sensor/color.ts +++ b/libs/color-sensor/color.ts @@ -11,6 +11,13 @@ const enum ColorSensorMode { ColorCal = 5, } +enum LightIntensityMode { + //% block="reflected light" + Reflected = ColorSensorMode.ReflectedLightIntensity, + //% block="ambient light" + Ambient = ColorSensorMode.AmbientLightIntensity +} + const enum ColorSensorColor { //% block="none" None, @@ -30,6 +37,13 @@ const enum ColorSensorColor { Brown, } +enum LightCondition { + //% block="dark" + Dark = sensors.internal.ThresholdState.Low, + //$ block="bright" + Bright = sensors.internal.ThresholdState.High +} + namespace sensors { /** @@ -38,15 +52,18 @@ namespace sensors { */ //% fixedInstances export class ColorSensor extends internal.UartSensor { + thresholdDetector: sensors.internal.ThresholdDetector; + constructor(port: number) { super(port) + this.thresholdDetector = new sensors.internal.ThresholdDetector(this.id()); } _deviceType() { return DAL.DEVICE_TYPE_COLOR } - setColorMode(m: ColorSensorMode) { + setMode(m: ColorSensorMode) { this._setMode(m) } @@ -66,6 +83,8 @@ namespace sensors { _update(prev: number, curr: number) { if (this.mode == ColorSensorMode.Color) control.raiseEvent(this._id, curr); + else + this.thresholdDetector.setLevel(curr); } /** @@ -82,7 +101,7 @@ namespace sensors { //% group="Color Sensor" onColorDetected(color: ColorSensorColor, handler: () => void) { control.onEvent(this._id, color, handler); - this.setColorMode(ColorSensorMode.Color) + this.setMode(ColorSensorMode.Color) if (this.color() == color) control.raiseEvent(this._id, color); } @@ -96,43 +115,54 @@ namespace sensors { //% blockId=colorGetColor //% parts="colorsensor" //% blockNamespace=sensors - //% weight=66 blockGap=8 + //% weight=99 //% group="Color Sensor" color(): ColorSensorColor { - this.setColorMode(ColorSensorMode.Color) + this.setMode(ColorSensorMode.Color) return this.getNumber(NumberFormat.UInt8LE, 0) } /** - * Measures the ambient light value from 0 (darkest) to 100 (brightest). - * @param color the color sensor port + * Registers code to run when the ambient light changes. + * @param condition the light condition + * @param handler the code to run when detected */ - //% help=sensors/color-sensor/ambient-light - //% block="`icons.colorSensor` %color| ambient light" - //% blockId=colorGetAmbient + //% help=sensors/color-sensor/on-light-changed + //% block="on `icons.colorSensor` %sensor|%mode|%condition" + //% blockId=colorOnLightChanged //% parts="colorsensor" //% blockNamespace=sensors - //% weight=65 blockGap=8 + //% weight=89 blockGap=8 //% group="Color Sensor" + onLightChanged(mode: LightIntensityMode, condition: LightCondition, handler: () => void) { + control.onEvent(this._id, condition, handler); + this.setMode(ColorSensorMode.AmbientLightIntensity) + } + + /** + * Measures the ambient or reflected light value from 0 (darkest) to 100 (brightest). + * @param color the color sensor port + */ + //% help=sensors/color-sensor/light + //% block="`icons.colorSensor` %color|%mode" + //% blockId=colorLight + //% parts="colorsensor" + //% blockNamespace=sensors + //% weight=88 + //% group="Color Sensor" + light(mode: LightIntensityMode) { + this.setMode(mode) + return this.getNumber(NumberFormat.UInt8LE, 0) + } + + //% ambientLight() { - this.setColorMode(ColorSensorMode.AmbientLightIntensity) - return this.getNumber(NumberFormat.UInt8LE, 0) + return this.light(LightIntensityMode.Ambient); } - /** - * Measures the reflected light value from 0 (darkest) to 100 (brightest). - * @param color the color sensor port - */ - //% help=sensors/color-sensor/reflected-light - //% block="`icons.colorSensor` %color| reflected light" - //% blockId=colorGetReflected - //% parts="colorsensor" - //% blockNamespace=sensors - //% weight=64 blockGap=8 - //% group="Color Sensor" - reflectedLight(): number { - this.setColorMode(ColorSensorMode.ReflectedLightIntensity) - return this.getNumber(NumberFormat.UInt8LE, 0) + //% + reflectedLight() { + return this.light(LightIntensityMode.Reflected); } } diff --git a/libs/core/input.ts b/libs/core/input.ts index 894c9203..05f39e89 100644 --- a/libs/core/input.ts +++ b/libs/core/input.ts @@ -177,7 +177,81 @@ namespace sensors.internal { } } + export enum ThresholdState { + Normal = 1, + High = 2, + Low = 3, + } + export class ThresholdDetector { + public id: number; + private min: number; + private max: number; + private lowThreshold: number; + private highThreshold: number; + private level: number; + private state: ThresholdState; + + constructor(id: number, min = 0, max = 100, lowThreshold = 20, highThreshold = 80) { + this.id = id; + this.min = min; + this.max = max; + this.lowThreshold = lowThreshold; + this.highThreshold = highThreshold; + this.level = Math.ceil((max - min) / 2); + this.state = ThresholdState.Normal; + } + + public setLevel(level: number) { + this.level = this.clampValue(level); + + if (this.level >= this.highThreshold) { + this.setState(ThresholdState.High); + } + else if (this.level <= this.lowThreshold) { + this.setState(ThresholdState.Low); + } + else { + this.setState(ThresholdState.Normal); + } + } + + public setLowThreshold(value: number) { + this.lowThreshold = this.clampValue(value); + this.highThreshold = Math.max(this.lowThreshold + 1, this.highThreshold); + } + + public setHighThreshold(value: number) { + this.highThreshold = this.clampValue(value); + this.lowThreshold = Math.min(this.highThreshold - 1, this.lowThreshold); + } + + private clampValue(value: number) { + if (value < this.min) { + return this.min; + } + else if (value > this.max) { + return this.max; + } + return value; + } + + private setState(state: ThresholdState) { + if (this.state == state) return; + + this.state = state; + switch (state) { + case ThresholdState.High: + control.raiseEvent(this.id, ThresholdState.High); + break; + case ThresholdState.Low: + control.raiseEvent(this.id, ThresholdState.Low); + break; + case ThresholdState.Normal: + break; + } + } + } export class UartSensor extends Sensor { protected mode: number // the mode user asked for