Compare commits

...

27 Commits

Author SHA1 Message Date
61996acdd9 0.0.73 2018-01-29 13:26:46 -08:00
21deb45728 fixing release fiber 2018-01-29 13:26:31 -08:00
34578d2370 0.0.72 2018-01-29 11:20:46 -08:00
3f50b5c39a updated pxt references + hero banner 2018-01-29 11:20:34 -08:00
d371225066 0.0.71 2018-01-23 14:53:09 -08:00
387effbdd0 upgraded to run in parallel 2018-01-23 14:52:41 -08:00
18480080e7 updated tutorial format 2018-01-19 15:42:23 -08:00
bf6a932e5f Color calibration (#245)
* better handling of thresholds, color calibration strategy

* updating calibration parameters
2018-01-19 13:11:11 -08:00
23bb316403 settle robot once brake is applied 2018-01-18 21:28:00 -08:00
138de504e5 minor high contrast fixes 2018-01-18 21:03:57 -08:00
df13e40a45 fixing make it move 2018-01-18 16:47:00 -08:00
511ea2374b fixing summary 2018-01-18 16:44:57 -08:00
db4ed6daf3 fixing a bunch of snippets 2018-01-18 16:43:16 -08:00
a60427e2cf using audio context manager function (#243)
* using audio context manager function

* updated pxt reference

* trigger build
2018-01-18 13:53:33 -08:00
ef5b4172e8 missing file logo 2018-01-18 12:42:11 -08:00
7baf7cfede 0.0.70 2018-01-18 12:13:17 -08:00
efd6718ea3 converted lesson to tutorial 2018-01-18 12:09:43 -08:00
057a1d66dc PID support (#242)
* updated block definitions

* updated dependency on common packages
2018-01-18 10:34:06 -08:00
5ddfcd5508 Prototype lesson 'Make it Move" (#241)
* Prototype lesson 'Make it Move"

* Wrong blockq type
2018-01-17 19:45:07 -08:00
00f0922189 Merge pull request #240 from Microsoft/line-detect-lesson
Prototype lesson for 'Line Detection'
2018-01-17 19:07:29 -08:00
41f4b64087 Add to gallerys 2018-01-17 18:52:49 -08:00
ea5ee1c007 Prototype lesson for 'Line Detection' 2018-01-17 17:02:11 -08:00
603e4c0fc1 0.0.69 2018-01-16 17:06:52 -08:00
e50c88008a updated gyrobox 2018-01-16 17:05:57 -08:00
f057964a50 pausing until sound is done in mood 2018-01-16 16:44:32 -08:00
2eda2061cf updated modified gyro boy 2018-01-16 16:26:49 -08:00
a4ebf4c746 moving moods in separate namespace 2018-01-16 16:21:02 -08:00
70 changed files with 1025 additions and 336 deletions

View File

@ -5,7 +5,7 @@
This repo contains the editor target hosted at https://d541eec2-1e96-4b7b-a223-da9d01d0337a.pxt.io/ This repo contains the editor target hosted at https://d541eec2-1e96-4b7b-a223-da9d01d0337a.pxt.io/
LEGO Auth: https://src.education.lego.com/groups/ev3-makecode (use Google Authenticator) LEGO Auth: https://src.education.lego.com/groups/ev3-makecode (use Google Authenticator)
LEGO Chat: https://chat.internal.education.lego.com/make-code/channels/town-square LEGO Chat: https://chat.internal.education.lego.com/make-code/channels/town-square
## Local Dev setup ## Local Dev setup

View File

@ -1,5 +1,43 @@
# @extends # @extends
## Projects #projects
* [Maker](/maker)
* [Sound Machine](/maker/sound-machine)
* [Sound of Color](/maker/sound-of-color)
* [Security Gadget](/maker/security-gadget)
* [Intruder detector](/maker/intruder-detector)
* [Puppet](/maker/puppet)
* [Coding](/coding)
* [Three Point Turn 1](/coding/three-point-turn-1)
* [Three Point Turn 2](/coding/three-point-turn-2)
* [Three Point Turn 3](/coding/three-point-turn-3)
* [Reversing the robot 1](/coding/reversing-the-robot-1)
* [Reversing the robot 2](/coding/reversing-the-robot-2)
* [Reversing the robot 3](/coding/reversing-the-robot-3)
* [Light the way 1](/coding/light-the-way-1)
* [Light the way 2](/coding/light-the-way-2)
* [Light the way 3](/coding/light-the-way-3)
* [Traffic Lights 1](/coding/traffic-lights-1)
* [Traffic Lights 2](/coding/traffic-lights-2)
* [Traffic Lights 3](/coding/traffic-lights-3)
* [Reverse Beeper 1](/coding/reverse-beeper-1)
* [Reverse Beeper 2](/coding/reverse-beeper-2)
* [Reverse Beeper 3](/coding/reverse-beeper-3)
* [Ignition 1](/coding/ignition-1)
* [Ignition 2](/coding/ignition-2)
* [Ignition 3](/coding/ignition-3)
* [Cruise Control 1](/coding/cruise-control-1)
* [Cruise Control 2](/coding/cruise-control-2)
* [Cruise Control 3](/coding/cruise-control-3)
* [Roaming 1](/coding/roaming-1)
* [Roaming 2](/coding/roaming-2)
* [Lessons](/lessons)
* [Make it move](/lessons/make-it-move)
* [Line detection](/lessons/line-detection)
## Reference #reference ## Reference #reference
* [Reference](/reference) * [Reference](/reference)

View File

@ -6,14 +6,14 @@ Welcome to the **Microsoft MakeCode** editor for the **@boardname@**!
You can program the @boardname@ using [Blocks](/blocks) or [JavaScript](/javascript) in your web browser: You can program the @boardname@ using [Blocks](/blocks) or [JavaScript](/javascript) in your web browser:
```block ```blocks
input.buttonA.onEvent(ButtonEvent.Click, () => { brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
light.showRing(`blue blue blue blue blue blue blue blue blue blue`) motors.largeA.setSpeed(50)
}) })
``` ```
```typescript ```typescript
input.buttonA.onEvent(ButtonEvent.Click, () => { brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
light.showRing(`blue blue blue blue blue blue blue blue blue blue`) motors.largeA.setSpeed(50)
}) })
``` ```
@ -22,10 +22,10 @@ The editor work in [most modern browsers](/browsers), work [offline](/offline) o
## [Compile and Flash: Your Program!](/device/usb) ## [Compile and Flash: Your Program!](/device/usb)
When you have your code ready, you connect your @boardname@ to a computer via a USB cable When you have your code ready, you connect your @boardname@ to a computer via a USB cable
**then press the reset button** so it appears as a mounted drive (named **CPLAYBOOT**). so it appears as a mounted drive (named **EV3**).
Compilation to machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the binary Compilation to machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the binary
program to a **.uf2** file, which you then copy to the **CPLAYBOOT** drive, which flashes the device with the new program. program to a **.uf2** file, which you then copy to the **EV3** drive, which flashes the device with the new program.
## Simulator: Test Your Code ## Simulator: Test Your Code
@ -33,11 +33,7 @@ You can run your code using the micro:bit simulator, all within the confines of
The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins. The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins.
```sim ```sim
loops.forever(() => { brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
light.pixels.showAnimation(light.animation(LightAnimation.Rainbow), 1000) motors.largeA.setSpeed(50)
}) })
``` ```
```package
light
```

View File

@ -3,13 +3,13 @@
```blocks ```blocks
let beep = false let beep = false
beep = true beep = true
control.runInBackground(function () { control.runInParallel(function () {
motors.largeBC.setSpeed(-20) motors.largeBC.setSpeed(-20)
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear) sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear)
motors.largeBC.stop() motors.largeBC.stop()
beep = false beep = false
}) })
control.runInBackground(function () { control.runInParallel(function () {
while (beep) { while (beep) {
if (sensors.ultrasonic4.distance() < 20) { if (sensors.ultrasonic4.distance() < 20) {
music.playTone(440, sensors.ultrasonic4.distance()) music.playTone(440, sensors.ultrasonic4.distance())

View File

@ -3,10 +3,10 @@
```blocks ```blocks
brick.buttonEnter.onEvent(ButtonEvent.Click, function () { brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
motors.largeBC.setSpeed(50) motors.largeBC.setSpeed(50)
sensors.touchSensor1.pauseUntil(TouchSensorEvent.Pressed) sensors.touch1.pauseUntil(TouchSensorEvent.Pressed)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)
loops.pause(1000) loops.pause(1000)
brick.setLight(LightsPattern.OrangeFlash) brick.setLight(BrickLight.OrangeFlash)
motors.largeBC.setSpeed(-50) motors.largeBC.setSpeed(-50)
loops.pause(2000) loops.pause(2000)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)

View File

@ -2,12 +2,12 @@
```blocks ```blocks
brick.buttonEnter.onEvent(ButtonEvent.Click, function () { brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
sensors.touchSensor1.pauseUntil(TouchSensorEvent.Pressed) sensors.touch1.pauseUntil(TouchSensorEvent.Pressed)
motors.largeBC.setSpeed(50) motors.largeBC.setSpeed(50)
sensors.touchSensor2.pauseUntil(TouchSensorEvent.Pressed) sensors.touch2.pauseUntil(TouchSensorEvent.Pressed)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)
loops.pause(1000) loops.pause(1000)
brick.setLight(LightsPattern.OrangeFlash) brick.setLight(BrickLight.OrangeFlash)
motors.largeBC.setSpeed(-50) motors.largeBC.setSpeed(-50)
loops.pause(2000) loops.pause(2000)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)

View File

@ -3,14 +3,14 @@
```blocks ```blocks
brick.buttonEnter.onEvent(ButtonEvent.Click, function () { brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
brick.showImage(images.eyesSleeping) brick.showImage(images.eyesSleeping)
sensors.touchSensor1.pauseUntil(TouchSensorEvent.Pressed) sensors.touch1.pauseUntil(TouchSensorEvent.Pressed)
brick.showImage(images.eyesNeutral) brick.showImage(images.eyesNeutral)
motors.largeBC.setSpeed(50) motors.largeBC.setSpeed(50)
sensors.touchSensor2.pauseUntil(TouchSensorEvent.Pressed) sensors.touch2.pauseUntil(TouchSensorEvent.Pressed)
brick.showImage(images.eyesTiredMiddle) brick.showImage(images.eyesTiredMiddle)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)
loops.pause(1000) loops.pause(1000)
brick.setLight(LightsPattern.OrangeFlash) brick.setLight(BrickLight.OrangeFlash)
brick.showImage(images.eyesDizzy) brick.showImage(images.eyesDizzy)
motors.largeBC.setSpeed(-50) motors.largeBC.setSpeed(-50)
loops.pause(2000) loops.pause(2000)

View File

@ -19,17 +19,13 @@ loops.pause(1000)
music.playSoundEffectUntilDone(sounds.communicationGo) music.playSoundEffectUntilDone(sounds.communicationGo)
for (let d of drive) { for (let d of drive) {
if (d == 1) { if (d == 1) {
motors.largeC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeC.pauseUntilReady()
} else if (d == 3) { } else if (d == 3) {
motors.largeB.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeB.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeB.pauseUntilReady()
} else if (d == 4) { } else if (d == 4) {
motors.largeBC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} else { } else {
motors.largeBC.setSpeedFor(-50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(-50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} }
} }
music.playSoundEffectUntilDone(sounds.communicationGameOver) music.playSoundEffectUntilDone(sounds.communicationGameOver)

View File

@ -23,17 +23,13 @@ loops.pause(1000)
music.playSoundEffectUntilDone(sounds.communicationGo) music.playSoundEffectUntilDone(sounds.communicationGo)
for (let d of drive) { for (let d of drive) {
if (d == 1) { if (d == 1) {
motors.largeC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeC.pauseUntilReady()
} else if (d == 3) { } else if (d == 3) {
motors.largeB.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeB.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeB.pauseUntilReady()
} else if (d == 4) { } else if (d == 4) {
motors.largeBC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} else { } else {
motors.largeBC.setSpeedFor(-50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(-50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} }
} }
music.playSoundEffectUntilDone(sounds.communicationGameOver) music.playSoundEffectUntilDone(sounds.communicationGameOver)

View File

@ -0,0 +1,178 @@
# Gyroboy
Work in progress
```blocks
let motorSpeed1 = 0
let motorSpeed2 = 0
let motorSpeed3 = 0
let motorSpeed = 0
let fallen = false
let motorSpeed0 = 0
let oldControlDrive = 0
let controlDrive = 0
let power = 0
let motorAngle = 0
let gyroAngle = 0
let controlSteering = 0
let state = 0
let motorPosition = 0
let temp = 0
let gyroRate = 0
let timestep = 0
sensors.color1.onColorDetected(ColorSensorColor.Red, function () {
music.playTone(2000, 100)
controlDrive = 0
controlSteering = 0
})
// reads the motor angle and computes the motor speed,
// position
function computeMotors() {
temp = motorAngle
// read angle on both motors
motorAngle = motors.largeD.angle() + motors.largeA.angle()
// and estimate speed as angle difference
motorSpeed0 = motorAngle - temp
// average last 4 speed readings
motorSpeed = (motorSpeed0 + motorSpeed1 + motorSpeed2 + motorSpeed3) / 4 / timestep
// shift all previous recorded speeds by one
motorSpeed3 = motorSpeed2
motorSpeed2 = motorSpeed1
motorSpeed1 = motorSpeed0
// compute position from speed
motorPosition = motorPosition + timestep * motorSpeed
}
// read the gyro rate and computes the angle
function computeGyro() {
gyroRate = sensors.gyro2.rate()
gyroAngle = gyroAngle + timestep * gyroRate
}
function reset() {
state = 0
// sleeping
moods.sleeping.show();
// reset counters
motors.largeA.reset()
motors.largeD.reset()
// motors are unregulated
motors.largeA.setRegulated(false)
motors.largeD.setRegulated(false)
// clear the gyro sensor to remove drift
sensors.gyro2.reset()
// fall detection timer
control.timer2.reset()
// timestep computation timer
control.timer3.reset()
motorAngle = 0
motorPosition = 0
motorSpeed = 0
motorSpeed0 = 0
motorSpeed1 = 0
motorSpeed2 = 0
motorSpeed3 = 0
gyroRate = 0
gyroAngle = 0
fallen = false
power = 0
controlSteering = 0
controlDrive = 0
// awake
moods.awake.show();
gyroAngle = -0.25
state = 1;
}
// compute set point for motor position and required
// motor power
function computePower() {
// apply control and compute desired motor position
motorPosition -= timestep * controlDrive;
// estimate power based on sensor readings and control
// values
power = 0.8 * gyroRate + 15 * gyroAngle + (0.08 * motorSpeed + 0.12 * motorPosition) - 0.01 * controlDrive
// ensure that power stays within -100, 100
if (power > 100) {
power = 100
} else if (power < -100) {
power = -100
}
}
// test if the robot has fallen off
function checkFallen() {
if (Math.abs(power) < 100) {
control.timer2.reset()
}
if (control.timer2.seconds() > 2) {
fallen = true
}
}
// stop all motors and wait for touch button to be
// pressed
function stop() {
motors.stopAllMotors()
state = 0
moods.knockedOut.show();
sensors.touch3.pauseUntil(TouchSensorEvent.Pressed)
moods.neutral.show();
}
sensors.ultrasonic4.onEvent(UltrasonicSensorEvent.ObjectNear, function () {
moods.dizzy.show()
controlSteering = 0
oldControlDrive = controlDrive
controlDrive = -10
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
motors.mediumC.setSpeed(-30, 60, MoveUnit.Degrees);
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
if (Math.randomRange(-1, 1) >= 1) {
controlSteering = 70
} else {
controlSteering = -70
}
loops.pause(4000)
music.playTone(2000, 100)
controlSteering = 0
controlDrive = oldControlDrive
moods.neutral.show()
})
// compute the elapsed time since the last iteration
function computeTimestep() {
timestep = control.timer3.seconds()
control.timer3.reset()
}
sensors.color1.onColorDetected(ColorSensorColor.Green, function () {
moods.winking.show()
controlDrive = 150
controlSteering = 0
})
sensors.color1.onColorDetected(ColorSensorColor.Blue, function () {
moods.middleRight.show()
controlSteering = 70
})
// apply power to motors
function controlMotors() {
motors.largeA.setSpeed(power + controlSteering * 0.1)
motors.largeD.setSpeed(power - controlSteering * 0.1)
}
sensors.color1.onColorDetected(ColorSensorColor.Yellow, function () {
moods.middleLeft.show()
controlSteering = -70
})
sensors.color1.onColorDetected(ColorSensorColor.White, function () {
moods.sad.show();
controlDrive = -75
})
timestep = 0.014
// main loop
loops.forever(function () {
reset()
while (!fallen) {
control.timer3.pauseUntil(5)
computeTimestep()
computeGyro()
computeMotors()
computePower()
controlMotors()
checkFallen()
}
stop()
})
```

View File

@ -81,7 +81,7 @@ function IS(t: number) {
function UP() { function UP() {
if (motors.largeA.angle() > -50) { if (motors.largeA.angle() > -50) {
control.runInBackground(function () { control.runInParallel(function () {
motors.largeD.clearCounts() motors.largeD.clearCounts()
motors.largeD.setSpeed(-35); motors.largeD.setSpeed(-35);
pauseUntil(() => motors.largeD.angle() < -25); pauseUntil(() => motors.largeD.angle() < -25);

View File

@ -3,10 +3,10 @@
Use a touch sensor to make the brick happy. Use a touch sensor to make the brick happy.
```blocks ```blocks
sensors.touchSensor1.onEvent(TouchSensorEvent.Pressed, function () { sensors.touch1.onEvent(TouchSensorEvent.Pressed, function () {
brick.showImage(images.expressionsBigSmile) brick.showImage(images.expressionsBigSmile)
}) })
sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { sensors.touch1.onEvent(TouchSensorEvent.Released, function () {
brick.showImage(images.expressionsSick) brick.showImage(images.expressionsSick)
}) })
``` ```

27
docs/lessons.md Normal file
View File

@ -0,0 +1,27 @@
# Lessons
Learning activities for LEGO Mindstorms with MakeCode.
## Motors and motion
```codecard
[{
"name": "Make it Move",
"imageUrl":"/static/lessons/make-it-move.jpg",
"url": "/lessons/make-it-move",
"cardType": "project",
"description": "Make a robot that moves itself without wheels."
}, {
"name": "Make it Move TUTORIAL",
"imageUrl":"/static/lessons/make-it-move.jpg",
"url": "/lessons/make-it-move-tutorial",
"cardType": "tutorial",
"description": "Make a robot that moves itself without wheels."
}, {
"name": "Line Detection",
"imageUrl":"/static/lessons/line-detection.jpg",
"url": "/lessons/line-detection",
"cardType": "project",
"description": "Make your robot drive itself by following lines."
}]
```

View File

@ -0,0 +1,266 @@
# Line Detection
## Objective
Design ways to improve driving safety by helping to prevent drivers from falling asleep and causing an accident.
![Car driving on highway](/static/lessons/line-detection/car-driving.jpg)
## Connect
Make sure that you can answer the following questions:
* Can autonomous cars react to different traffic light signals?
* What can happen if a driver falls asleep while driving?
* How can we detect when a driver is falling asleep?
Think about what you have learned, then document it. Describe the problem in your own words. Creatively record your ideas and findings.
## Construct
Start by constructing this model. Read the building instructions [here](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-color-sensor-down-driving-base-d30ed30610c3d6647d56e17bc64cf6e2.pdf) first.
![Color sensor on the driving base](/static/lessons/line-detection/color-sensor-driving.jpg)
## Program
Autonomous cars need to recognize and respond to traffic lights automatically.
First, create a program that will make your robot stop at red lights.
Make sure your robot is only responding to the color red.
Once you have succeeded, program your robot to drive forward again when the light changes from red to green.
There are two coding tasks for this lesson:
1. Create a program that will make your robot stop at red lights.
2. Create a program that drives the robot forward until the Color Sensor sees red. The robot then stops.
## Coding task 1 - Stop at red lights
**Goal:** Create a program that will make your robot stop at red lights.
### Step 1
Create a program that drives the robot forward until the Color Sensor sees red. The robot then stops.
Place a ``||motors:steer large B+C||`` block from ``||motors:Motors||`` under ``||loops:on start||``. Change the speed to 20%.
```blocks
motors.largeBC.steer(0, 20)
```
### Step 2
Place a ``||loops:while||`` loop block under ``||motors:steer large B+C||``.
```blocks
motors.largeBC.steer(0, 20)
while (true) {
}
```
### Step 3
Place a ``||sensors:pause for color||`` from ``||sensors:Sensors||`` inside the ``||loops:while||`` loop block. Change the color to red.
```blocks
motors.largeBC.steer(0, 20)
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Red)
}
```
### Step 4
Place a ``||motors:stop all motors||`` block under the ``||sensors:pause for color||`` block.
Study the program...what do you think the program will do?
**Hint:** The motors will run until the Color Sensor senses the color red, then all motors will stop. The motors will run until the sensor reading in the while block is true.
```blocks
motors.largeBC.steer(0, 20)
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Red)
motors.stopAllMotors()
}
```
### Step 5
Click `|Download|` and follow the instructions to get your code onto your EV3 Brick. Press the **center** button on the EV3 Brick to run the program.
## Coding task 2 - Detect light changes
**Goal:** Program your robot to drive forward again when the light changes from red to green.
### Step 1
Place a ``||loops:while||`` loop block under ``||loops:on start||``.
```blocks
while (true) {
}
```
### Step 2
Place a ``||motors:steer large B+C||`` block from ``||motors:Motors||`` inside the ``||loops:while||`` loop block. Change the speed to 20%.
```blocks
while (true) {
motors.largeBC.steer(0, 20)
}
```
### Step 4
Place a ``||loops:while||`` loop block under the ``||motors:steer large B+C||`` block.
```blocks
while (true) {
motors.largeBC.steer(0, 20)
while (true) {
}
}
```
### Step 5
Place a ``||sensors:pause for color||`` block from ``||sensors:Sensors||`` inside the ``||loops:while||`` loop block. Change the color to red.
```blocks
while (true) {
motors.largeBC.steer(0, 20)
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Red)
}
}
```
### Step 6
Place a ``||motors:stop all motors||`` block under the ``||sensors:pause for color||`` block.
```blocks
while (true) {
motors.largeBC.steer(0, 20)
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Red)
motors.stopAllMotors()
}
}
```
### Step 7
Place a ``||loops:while||`` loop block under the second ``||loops:while||`` loop block.
```blocks
while (true) {
motors.largeBC.steer(0, 20)
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Red)
motors.stopAllMotors()
}
while (true) {
}
}
```
### Step 8
Place a ``||sensors:pause for color||`` block inside the new ``||loops:while||`` loop block. Change the color to red.
What do you think the program will do?
**Hint:** The motors will run until the Color Sensor detects the color red, then it will stop all motors. The motors will also run and not stop when the color sensor detects the color green.
```blocks
while (true) {
motors.largeBC.steer(0, 20)
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Red)
motors.stopAllMotors()
}
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Red)
}
}
```
### Step 9
Click `|Download|` and follow the instructions to get your code onto your EV3 Brick. Press the **center** button on the EV3 Brick to run the program.
## Contemplate
To simulate what could happen if a driver falls asleep while driving, your robot could sound an alarm signal when it crosses the line. This feature is often available in new cars.
Program your robot to perform this function.
Think about what you have learned, then document it. Describe your pseudocode for this task. Creatively record your ideas, and findings.
### Programming hint
```blocks
motors.largeBC.steer(0, 20)
while (true) {
sensors.color3.pauseForColor(ColorSensorColor.Yellow)
music.playSoundEffect(sounds.systemGeneralAlert)
}
while (true) {
while (true) { sensors.color3.pauseForLight(LightIntensityMode.Reflected, LightCondition.Bright)
motors.largeB.setSpeed(10)
motors.largeC.setSpeed(-10)
}
while (true) {
sensors.color3.pauseForLight(LightIntensityMode.Reflected, LightCondition.Bright)
motors.largeA.setSpeed(-10)
motors.largeA.setSpeed(10)
}
}
```
## Continue
Program your robot to drive on “autopilot” along a given route. You will need to create a program that recognizes and responds to a dark line (or white line). You will create a line-following program and your robot will need to travel along the line without losing contact with it.
You will need to constantly debug your program in order to make your robot travel as smoothly as possible along the line.
### Programming hint
```blocks
while (true) {
while (true) { sensors.color3.pauseForLight(LightIntensityMode.Reflected, LightCondition.Bright)
motors.largeB.setSpeed(10)
motors.largeC.setSpeed(-10)
}
while (true) {
sensors.color3.pauseForLight(LightIntensityMode.Reflected, LightCondition.Bright)
motors.largeB.setSpeed(-10)
motors.largeC.setSpeed(10)
}
}
```
## Share
Consider the following questions:
1. What challenged you?
2. Where there any surprises?
3. How could you improve your program?
4. Could your program have been more streamlined?
5. Have you used too many blocks?
6. Is there a more efficient way of building your program?
7. How could your program be used in real-world scenarios?
Think about what you have learned, then document it. Creatively record and present your ideas, creations, and findings.

View File

@ -0,0 +1,72 @@
# Make It Move Without Wheels
## Objective @unplugged
Design, build and program a robot that can move itself:
Your robot will:
* Go a distance of at least 30cm
* Use at least one motor
* Use NO wheels for locomotion
![LECG Mindstorms brick with parts](/static/lessons/make-it-move/locomotion-no-wheels.jpg)
## Construct @unplugged
Build a Walker Bot!
The Walker Bot is one example of many possible solutions for making a robot move without wheels.
The Walker Bot combines an EV3 Frame and two legs that are mirror-images to create left and right legs.
The legs in the Walker Bot are designed to show how to change the rotary motion of a motor to reciprocating motion.
Start by reading [these](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/ev3-dep/building%20instructions/walker-bot-bi-180fc24f9298e1dd6201099627d43903.pdf) instructions first.
![LEGO Mindstorms Walker Bot](/static/lessons/make-it-move/walker-bot.jpg)
## Program 1 @fullscreen
In nature, creatures use many methods to get around. None of them, however, use wheels to move. Can we copy the method of animal locomotion with our robot? Using motors and legs, make the robot move without using any wheels.
Place a ``||motors:tank large B+C||`` block from ``||motors:Motors||`` under ``||loops:on start||``.
Change the speed to `-60%` (for motor B) and `+60%` (for motor C).
Change the rotations to `9`.
The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick. The motors are set for the reverse direction because they are mounted upside down in this model.
```blocks
motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
```
## Program 2 @fullscreen
Place a ``||motors:stop all motors||`` block under ``||motors:tank large B+C||``.
The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop.
```blocks
motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
motors.stopAllMotors()
```
## Program 3 @fullscreen
Place a ``||brick:show string||`` block under ``||motors:stop all motors||``.
Change the `"Hello World"` text to `"30 cm"`.
The ``||motors:tank large B+C||`` will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop and display "30 cm" on the EV3 Bricks screen.
```blocks
motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
motors.stopAllMotors()
brick.showString("30 cm", 1)
```
## Download @fullscreen
Click `|Download|` and follow the instructions to get your code onto your EV3 Brick. Press the **center** button on the EV3 Brick to run the program.

View File

@ -0,0 +1,73 @@
# Make It Move Without Wheels
## Objective
Design, build and program a robot that can move itself:
Your robot will:
* Go a distance of at least 30cm
* Use at least one motor
* Use NO wheels for locomotion
![LECG Mindstorms brick with parts](/static/lessons/make-it-move/locomotion-no-wheels.jpg)
## Construct
Build a Walker Bot!
The Walker Bot is one example of many possible solutions for making a robot move without wheels.
The Walker Bot combines an EV3 Frame and two legs that are mirror-images to create left and right legs.
The legs in the Walker Bot are designed to show how to change the rotary motion of a motor to reciprocating motion.
Start by reading [these](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/ev3-dep/building%20instructions/walker-bot-bi-180fc24f9298e1dd6201099627d43903.pdf) instructions first.
![LEGO Mindstorms Walker Bot](/static/lessons/make-it-move/walker-bot.jpg)
## Program
In nature, creatures use many methods to get around. None of them, however, use wheels to move. Can we copy the method of animal locomotion with our robot? Using motors and legs, make the robot move without using any wheels.
### Step 1
Place a ``||motors:tank large B+C||`` block from ``||motors:Motors||`` under ``||loops:on start||``.
Change the speed to `-60%` (for motor B) and `+60%` (for motor C).
Change the rotations to `9`.
The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick. The motors are set for the reverse direction because they are mounted upside down in this model.
```blocks
motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
```
### Step 2
Place a ``||motors:stop all motors||`` block under ``||motors:tank large B+C||``.
The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop.
```blocks
motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
motors.largeBC.stop()
```
### Step 3
Place a ``||brick:show string||`` block under ``||motors:stop all motors||``.
Change the `"Hello World"` text to `"30 cm"`.
The ``||motors:tank large B+C||`` will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop and display "30 cm" on the EV3 Bricks screen.
```blocks
motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
motors.largeBC.stop()
brick.showString("30 cm", 1)
```
### Step 4
Click `|Download|` and follow the instructions to get your code onto your EV3 Brick. Press the **center** button on the EV3 Brick to run the program.

View File

@ -2,10 +2,8 @@
This program will activate an alarm when an object moves in front of the Ultrasonic Sensor. This program will activate an alarm when an object moves in front of the Ultrasonic Sensor.
TODO support for event when value changes
```blocks ```blocks
input.ultrasonic4.onObjectNear(function () { sensors.ultrasonic4.onEvent(UltrasonicSensorEvent.ObjectNear, function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp)) music.playSoundEffectUntilDone(sounds.informationActivate)
}) })
``` ```

View File

@ -4,14 +4,12 @@ Use this program with the Programmable Brick and Large Motor.
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
output.largeMotorA.setPower(30) motors.largeA.setSpeed(30)
output.largeMotorA.on(true)
loops.pause(100) loops.pause(100)
output.largeMotorA.on(false) motors.largeA.stop()
music.playSoundUntilDone(music.sounds(Sounds.PowerUp)) music.playSoundEffectUntilDone(sounds.animalsCatPurr)
output.largeMotorA.setPower(-30) motors.largeA.setSpeed(-30)
output.largeMotorA.on(true)
loops.pause(100) loops.pause(100)
output.largeMotorA.on(false) motors.largeA.stop()
}) })
``` ```

View File

@ -3,7 +3,7 @@
This program will activate an alarm when an object is lifted from the Touch Sensor. This program will activate an alarm when an object is lifted from the Touch Sensor.
```blocks ```blocks
input.touchSensor1.onEvent(TouchSensorEvent.Released, function () { sensors.touch1.onEvent(TouchSensorEvent.Released, function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp)) music.playSoundEffectUntilDone(sounds.informationActivate);
}) })
``` ```

View File

@ -4,9 +4,9 @@ This example program combined with the small model will make a beat and rhythm o
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
output.motorA.on(50) motors.largeA.setSpeed(50)
loops.pause(200) loops.pause(200)
output.motorA.on(100) motors.largeA.setSpeed(100)
loops.pause(200) loops.pause(200)
}) })
``` ```

View File

@ -3,13 +3,13 @@
This program will play different sounds when the wheel is rotated. The sound is determined by which color is placed in front of the color Sensor. This program will play different sounds when the wheel is rotated. The sound is determined by which color is placed in front of the color Sensor.
```blocks ```blocks
input.color3.onColorDetected(ColorSensorColor.Blue, function () { sensors.color3.onColorDetected(ColorSensorColor.Blue, function () {
music.playTone(Note.G4, music.beat(BeatFraction.Half)) music.playTone(Note.G4, music.beat(BeatFraction.Half))
}) })
input.color3.onColorDetected(ColorSensorColor.Red, function () { sensors.color3.onColorDetected(ColorSensorColor.Red, function () {
music.playTone(Note.C5, music.beat(BeatFraction.Half)) music.playTone(Note.C5, music.beat(BeatFraction.Half))
}) })
input.color3.onColorDetected(ColorSensorColor.Green, function () { sensors.color3.onColorDetected(ColorSensorColor.Green, function () {
music.playTone(Note.D5, music.beat(BeatFraction.Half)) music.playTone(Note.D5, music.beat(BeatFraction.Half))
}) })
``` ```

4
docs/static/filelogo.svg vendored Normal file
View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path fill="#aa278f" d="M32 15.994v-.011c0-.108-.005-.209-.016-.303h-.001c-.032-.285-.112-.504-.239-.656-.171-.204-.459-.435-.864-.691a4.275 4.275 0 0 1-.986-.827c-.252-.296-.442-.734-.57-1.316-.049-.227-.087-.719-.112-1.473V8.696c0-.38-.031-.723-.076-1.049a12.313 12.313 0 0 0-.004-.188c-.009-.782-.18-1.475-.513-2.078a3.462 3.462 0 0 0-1.416-1.401c-.611-.33-1.305-.495-2.081-.495H6.271s-.674.067-.962.201a4.021 4.021 0 0 0-.521.295 3.502 3.502 0 0 0-.798.59c-.693.688-1.061 1.601-1.113 2.734a9.172 9.172 0 0 0-.088 1.283v2.558a6.802 6.802 0 0 1-.183 1.373 2.311 2.311 0 0 1-.532 1.033 2.67 2.67 0 0 0-.202.196c-.265.238-.638.511-1.13.823-.404.262-.64.633-.715 1.108l-.002.023a2.195 2.195 0 0 0-.023.287L0 16.006v.011c0 .108.005.209.016.303h.001c.032.285.112.504.239.656.171.204.459.435.864.691.406.256.735.532.986.827.252.296.442.734.57 1.316.049.227.087.719.112 1.473v2.019c0 .38.031.723.076 1.049l.004.188c.009.782.18 1.475.513 2.078a3.462 3.462 0 0 0 1.416 1.401c.611.33 1.305.495 2.081.495H25.73c.35 0 .673-.067.961-.201.184-.085.356-.187.521-.296.291-.159.559-.353.798-.59.693-.688 1.061-1.601 1.113-2.734.056-.398.088-.823.088-1.283v-2.558c.019-.495.079-.953.183-1.373.104-.419.282-.762.532-1.033a2.67 2.67 0 0 0 .202-.196c.265-.238.638-.511 1.13-.823.404-.262.64-.633.715-1.108h.002l.002-.023c.013-.092.022-.187.023-.287v-.014z"/>
<path fill="#fff" d="M27.366 16.522l.819-.518-.821-.516a4.547 4.547 0 0 1-.927-.744 3.033 3.033 0 0 1-.554-.896 5.166 5.166 0 0 1-.328-1.339 16.319 16.319 0 0 1-.103-1.961c0-.781-.016-1.365-.05-1.786-.039-.489-.123-.852-.258-1.112a1.36 1.36 0 0 0-.718-.661c-.223-.089-.527-.154-.924-.199a.532.532 0 0 1-.356-.213c-.11-.133-.165-.344-.165-.627 0-.41.086-.811 1.121-.811.636 0 1.196.127 1.666.376.464.247.818.589 1.085 1.046.267.458.406.995.413 1.597.064 3.554.129 4.265.184 4.492.153.63.382 1.109.701 1.464.287.319.635.602 1.035.843.29.175.501.341.627.493.035.043.116.181.116.554 0 .383-.12.628-.39.794-.606.373-1.041.699-1.331.997a2.734 2.734 0 0 0-.678 1.24c-.112.437-.177 1.05-.198 1.875-.02.773-.042 1.741-.066 2.904-.021.941-.306 1.668-.873 2.222-.568.554-1.317.823-2.291.823-.409 0-.71-.077-.895-.23-.155-.128-.226-.32-.226-.604 0-.179.03-.336.093-.479a.682.682 0 0 1 .188-.268.463.463 0 0 1 .24-.094c.414-.055.725-.127.951-.219.317-.131.567-.378.723-.716.124-.269.2-.625.233-1.089.029-.402.044-.968.044-1.725.016-1.061.077-1.896.182-2.481.095-.53.274-.987.533-1.359.261-.375.665-.736 1.198-1.073zm-16.618 6.519h10.458a.75.75 0 0 0 .751-.751l-.001-3.709c-.134-.449-.518-.492-.878-.15-.033 0-.393.443-1.22.443a2.033 2.033 0 0 1-1.944-1.715h-.011a6.59 6.59 0 0 1 0-.526h.011a2.03 2.03 0 0 1 1.944-1.715c.827 0 1.187.443 1.22.443.35.332.738.252.879-.147l.001-3.432a.769.769 0 0 0-.562-.741c-.061.016-3.259 0-3.259 0-.786.065-1.063-.466-.624-.928 0-.033.443-.393.443-1.22a2.033 2.033 0 0 0-1.715-1.944v-.011a6.59 6.59 0 0 0-.526 0v.011A2.03 2.03 0 0 0 14 8.893c0 .827.443 1.187.443 1.22.439.462.254.97-.624.928 0 0-3.198.016-3.259 0a.77.77 0 0 0-.562.741V22.29a.75.75 0 0 0 .75.751zm-6.197-3.692c.055.227.12.938.184 4.492.007.602.146 1.138.413 1.597.267.458.622.8 1.085 1.046.47.25 1.03.376 1.666.376 1.035 0 1.121-.4 1.121-.811 0-.283-.056-.493-.165-.627a.537.537 0 0 0-.356-.213c-.397-.045-.701-.11-.925-.199a1.367 1.367 0 0 1-.718-.661c-.135-.259-.219-.623-.258-1.112a24.159 24.159 0 0 1-.05-1.786c0-.751-.035-1.41-.103-1.961a5.174 5.174 0 0 0-.329-1.339 3.028 3.028 0 0 0-.554-.896 4.52 4.52 0 0 0-.927-.744l-.821-.516.819-.518c.533-.337.936-.698 1.199-1.075.259-.372.438-.829.533-1.359.105-.585.166-1.419.182-2.481 0-.757.014-1.323.044-1.725.033-.464.109-.82.233-1.089.156-.337.406-.584.723-.715.226-.092.537-.163.951-.219a.463.463 0 0 0 .24-.094.662.662 0 0 0 .189-.267 1.18 1.18 0 0 0 .093-.479c0-.284-.072-.476-.226-.604-.186-.153-.487-.23-.895-.23-.974 0-1.723.269-2.291.823-.567.554-.852 1.281-.873 2.222a588.806 588.806 0 0 1-.065 2.904c-.021.825-.086 1.438-.198 1.875a2.731 2.731 0 0 1-.679 1.24c-.289.298-.725.624-1.331.997-.27.166-.39.41-.39.794 0 .373.081.511.116.554.127.153.338.319.627.493.4.24.748.524 1.035.843.319.355.548.834.701 1.464z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
docs/static/hero.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 585 KiB

BIN
docs/static/lessons/line-detection.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
docs/static/lessons/make-it-move.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,26 @@
{
"automation": "Automation, process control and robotic controllers",
"automation.Behavior": "A behavior",
"automation.Behavior.update": "Called on each behavior iteration even for suppresed behaviors",
"automation.Behavior.update|param|elapsed": "milli seconds since last call",
"automation.BehaviorManager": "A manager for behaviors",
"automation.BehaviorManager.add": "Adds a new behavior to the behavior manager",
"automation.BehaviorManager.add|param|behavior": "the behavior to add",
"automation.BehaviorManager.start": "Starts the behavior control loop",
"automation.BehaviorManager.stop": "Stops the execution loop",
"automation.PIDController": "A PID controller.\n* Reference: Feedback System, Karl Johan Astrom & Rickard M. Murry",
"automation.PIDController.compute": "Computes the output based on the system state",
"automation.PIDController.setControlSaturation": "Sets the control saturation values",
"automation.PIDController.setControlSaturation|param|high": "highest control value, eg: 100",
"automation.PIDController.setControlSaturation|param|low": "lowest control value, eg: -100",
"automation.PIDController.setDerivativeFilter": "Sets the derivative filter gain",
"automation.PIDController.setDerivativeFilter|param|N": "the filter gain, eg:10",
"automation.PIDController.setGains": "Sets the PID gains",
"automation.PIDController.setGains|param|b": "setpoint weight, eg: 0.9",
"automation.PIDController.setGains|param|kd": "derivative gain",
"automation.PIDController.setGains|param|ki": "integral gain",
"automation.PIDController.setGains|param|kp": "proportional gain",
"automation.PIDController.setPoint": "Updates the desired setpoint",
"automation.addBehavior": "Adds the behavior and starts it",
"automation.addBehavior|param|behavior": "a behavior"
}

View File

@ -0,0 +1,12 @@
{
"automation.PIDController.compute|block": "%pid|compute for timestep %timestep|(ms) at state %y",
"automation.PIDController.setControlSaturation|block": "set %pid|control saturation from %low|to %high",
"automation.PIDController.setDerivativeFilter|block": "set %pid|derivative filter %N",
"automation.PIDController.setGains|block": "set %pid|gains kp %kp|ki %ki|kd %kd",
"automation.PIDController.setPoint|block": "set %pid|point to %ysp",
"automation.addBehavior|block": "add behavior %behavior",
"automation|block": "automation",
"{id:category}Automation": "Automation",
"{id:group}Behaviors": "Behaviors",
"{id:group}PID": "PID"
}

View File

@ -1,6 +1,6 @@
{ {
"additionalFilePath": "../../node_modules/pxt-common-packages/libs/behaviors", "additionalFilePath": "../../node_modules/pxt-common-packages/libs/automation",
"dependencies": { "dependencies": {
"core": "file:../ev3" "ev3": "file:../ev3"
} }
} }

View File

@ -134,7 +134,7 @@
"control.panic": "Display an error code and stop the program.", "control.panic": "Display an error code and stop the program.",
"control.panic|param|code": "an error number to display. eg: 5", "control.panic|param|code": "an error number to display. eg: 5",
"control.reset": "Reset the device.", "control.reset": "Reset the device.",
"control.runInBackground": "Run other code in the background.", "control.runInParallel": "Run other code in the parallel.",
"control.waitForEvent": "Blocks the calling thread until the specified event is raised.", "control.waitForEvent": "Blocks the calling thread until the specified event is raised.",
"control.waitMicros": "Block the current fiber for the given microseconds", "control.waitMicros": "Block the current fiber for the given microseconds",
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4", "control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",

View File

@ -25,10 +25,11 @@
"control.onEvent|block": "on event|from %src|with value %value", "control.onEvent|block": "on event|from %src|with value %value",
"control.panic|block": "panic %code", "control.panic|block": "panic %code",
"control.reset|block": "reset", "control.reset|block": "reset",
"control.runInBackground|block": "run in background", "control.runInParallel|block": "run in parallel",
"control.waitForEvent|block": "wait for event|from %src|with value %value", "control.waitForEvent|block": "wait for event|from %src|with value %value",
"control.waitMicros|block": "wait (µs)%micros", "control.waitMicros|block": "wait (µs)%micros",
"control|block": "control", "control|block": "control",
"fieldeditors|block": "fieldeditors",
"loops.forever|block": "forever", "loops.forever|block": "forever",
"loops.pause|block": "pause %pause=timePicker|ms", "loops.pause|block": "pause %pause=timePicker|ms",
"loops|block": "loops", "loops|block": "loops",

View File

@ -17,7 +17,8 @@
"control.cpp", "control.cpp",
"control.ts", "control.ts",
"serial.cpp", "serial.cpp",
"serial.ts" "serial.ts",
"fieldeditors.ts"
], ],
"testFiles": [ "testFiles": [
"test.ts" "test.ts"

View File

@ -118,11 +118,11 @@ declare namespace control {
function waitMicros(micros: int32): void; function waitMicros(micros: int32): void;
/** /**
* Run other code in the background. * Run other code in the parallel.
*/ */
//% help=control/run-in-background blockAllowMultiple=1 afterOnStart=true //% help=control/run-in-parallel handlerStatement=1
//% blockId="control_run_in_background" block="run in background" blockGap=8 shim=control::runInBackground //% blockId="control_run_in_parallel" block="run in parallel" blockGap=8 shim=control::runInParallel
function runInBackground(a: () => void): void; function runInParallel(a: () => void): void;
/** /**
* Blocks the calling thread until the specified event is raised. * Blocks the calling thread until the specified event is raised.

View File

@ -1,14 +0,0 @@
{
"behaviors": "Behavior drive blocks",
"behaviors.Behavior": "A behavior",
"behaviors.BehaviorManager": "A manager for behaviors",
"behaviors.BehaviorManager.add": "Adds a new behavior to the behavior manager",
"behaviors.BehaviorManager.add|param|behavior": "the behavior to add",
"behaviors.BehaviorManager.start": "Starts the behavior control loop",
"behaviors.BehaviorManager.stop": "Stops the execution loop",
"behaviors.addBehavior": "Adds the behavior and starts it",
"behaviors.addBehavior|param|behavior": "a behavior",
"behaviors.avoidCrash": "A behavior that stops all motors if the sensor distance get too short",
"behaviors.driveForward": "A behavior that turns on the motors to the specified speed",
"behaviors.driveForward|param|motors": "@param speed the desired speed, eg: 50"
}

View File

@ -1,7 +0,0 @@
{
"behaviors.addBehavior|block": "add behavior %behavior",
"behaviors.avoidCrash|block": "avoid crash using %ultrasonic",
"behaviors.driveForward|block": "drive %motors|forward at %speed=motorSpeedPicker|%",
"behaviors|block": "behaviors",
"{id:category}Behaviors": "Behaviors"
}

View File

@ -1,56 +0,0 @@
namespace behaviors {
class AvoidCrashBehavior extends behaviors.Behavior {
private ultrasonic: sensors.UltraSonicSensor;
constructor(ultrasonic: sensors.UltraSonicSensor) {
super();
this.ultrasonic = ultrasonic;
}
shouldRun(): boolean {
return this.ultrasonic.distance() < 5;
}
run(): void {
motors.stopAllMotors();
this.active = false;
}
}
/**
* A behavior that stops all motors if the sensor distance get too short
*/
//% blockId=behaviorsAvoidCrash block="avoid crash using %ultrasonic"
export function avoidCrash(ultrasonic: sensors.UltraSonicSensor) : behaviors.Behavior {
return new AvoidCrashBehavior(ultrasonic);
}
class DriveForwardBehavior extends behaviors.Behavior {
private motors: motors.MotorBase;
private speed: number;
constructor(motors: motors.MotorBase, speed: number) {
super();
this.motors = motors;
this.speed = speed;
}
shouldRun(): boolean {
return true;
}
run(): void {
this.motors.setSpeed(this.speed);
pauseUntil(() => !this.active);
this.motors.setSpeed(0);
}
}
/**
* A behavior that turns on the motors to the specified speed
* @param motors
* @param speed the desired speed, eg: 50
*/
//% blockId=behaviorsDriveForward block="drive %motors|forward at %speed=motorSpeedPicker|%"
export function driveForward(motors: motors.MotorBase, speed: number): behaviors.Behavior {
return new DriveForwardBehavior(motors, speed);
}
}

View File

@ -1,5 +1,6 @@
{ {
"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": "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.calibrateLight": "Collects measurement of the light condition and adjusts the threshold to 10% / 90%.",
"sensors.ColorSensor.color": "Get the current color from the color sensor.", "sensors.ColorSensor.color": "Get the current color from the color sensor.",
"sensors.ColorSensor.colorMode": "Gets the current color mode", "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.light": "Measures the ambient or reflected light value from 0 (darkest) to 100 (brightest).",

View File

@ -13,6 +13,7 @@
"LightCondition.Dark|block": "dark", "LightCondition.Dark|block": "dark",
"LightIntensityMode.Ambient|block": "ambient light", "LightIntensityMode.Ambient|block": "ambient light",
"LightIntensityMode.Reflected|block": "reflected light", "LightIntensityMode.Reflected|block": "reflected light",
"sensors.ColorSensor.calibrateLight|block": "calibrate|%sensor|for %mode|light",
"sensors.ColorSensor.color|block": "%sensor| color", "sensors.ColorSensor.color|block": "%sensor| color",
"sensors.ColorSensor.light|block": "%sensor|%mode", "sensors.ColorSensor.light|block": "%sensor|%mode",
"sensors.ColorSensor.onColorDetected|block": "on %sensor|detected color %color", "sensors.ColorSensor.onColorDetected|block": "on %sensor|detected color %color",

View File

@ -39,9 +39,9 @@ const enum ColorSensorColor {
enum LightCondition { enum LightCondition {
//% block="dark" //% block="dark"
Dark = sensors.internal.ThresholdState.Low, Dark = sensors.ThresholdState.Low,
//$ block="bright" //$ block="bright"
Bright = sensors.internal.ThresholdState.High Bright = sensors.ThresholdState.High
} }
namespace sensors { namespace sensors {
@ -52,12 +52,14 @@ namespace sensors {
*/ */
//% fixedInstances //% fixedInstances
export class ColorSensor extends internal.UartSensor { export class ColorSensor extends internal.UartSensor {
thresholdDetector: sensors.internal.ThresholdDetector; thresholdDetector: sensors.ThresholdDetector;
calibrating: boolean;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this._setMode(ColorSensorMode.None); this._setMode(ColorSensorMode.None);
this.thresholdDetector = new sensors.internal.ThresholdDetector(this.id()); this.thresholdDetector = new sensors.ThresholdDetector(this.id());
this.calibrating = false;
} }
_colorEventValue(value: number) { _colorEventValue(value: number) {
@ -95,6 +97,7 @@ namespace sensors {
} }
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
if (this.calibrating) return; // simply ignore data updates while calibrating
if (this.mode == ColorSensorMode.Color) if (this.mode == ColorSensorMode.Color)
control.raiseEvent(this._id, this._colorEventValue(curr)); control.raiseEvent(this._id, this._colorEventValue(curr));
else else
@ -230,18 +233,65 @@ namespace sensors {
//% blockId=colorSetThreshold block="set %sensor|%condition|to %value" //% blockId=colorSetThreshold block="set %sensor|%condition|to %value"
//% group="Threshold" blockGap=8 weight=90 //% group="Threshold" blockGap=8 weight=90
//% value.min=0 value.max=100 //% value.min=0 value.max=100
//% sensor.fieldEditor="ports"
setThreshold(condition: LightCondition, value: number) { setThreshold(condition: LightCondition, value: number) {
if (condition == LightCondition.Dark) if (condition == LightCondition.Dark)
this.thresholdDetector.setLowThreshold(value) this.thresholdDetector.setLowThreshold(value)
else else
this.thresholdDetector.setHighThreshold(value); this.thresholdDetector.setHighThreshold(value);
} }
/**
* Collects measurement of the light condition and adjusts the threshold to 10% / 90%.
*/
//% blockId=colorCalibrateLight block="calibrate|%sensor|for %mode|light"
//% group="Threshold" weight=91 blockGap=8
//% sensor.fieldEditor="ports"
calibrateLight(mode: LightIntensityMode, deviation: number = 8) {
this.calibrating = true; // prevent events
this.light(mode); // trigger a read
pauseUntil(() => this.isActive()); // ensure sensor is live
let vold = 0;
let vcount = 0;
let min = 200;
let max = -200;
let k = 0;
while(k++ < 1000 && vcount < 50) {
let v = this.light(mode);
min = Math.min(min, v);
max = Math.max(max, v);
// detect if nothing has changed and stop calibration
if (Math.abs(v - vold) <= 2)
vcount ++;
else {
vold = v;
vcount = 1;
}
// wait a bit
loops.pause(50);
}
// apply tolerance
const minDist = 10;
min = Math.max(minDist / 2, Math.min(min + deviation / 2, max - deviation / 2 - minDist / 2));
max = Math.min(100 - minDist / 2, Math.max(min + minDist, max - deviation / 2));
// apply thresholds
this.thresholdDetector.setLowThreshold(min);
this.thresholdDetector.setHighThreshold(max);
this.calibrating = false;
}
} }
//% whenUsed block="color 3" weight=90 fixedInstance jres=icons.port3 //% whenUsed block="color 3" weight=95 fixedInstance jres=icons.port3
export const color3: ColorSensor = new ColorSensor(3) export const color3: ColorSensor = new ColorSensor(3)
//% whenUsed block="color 1" weight=95 fixedInstance jres=icons.port1 //% whenUsed block="color 1" weight=90 fixedInstance jres=icons.port1
export const color1: ColorSensor = new ColorSensor(1) export const color1: ColorSensor = new ColorSensor(1)
//% whenUsed block="color 2" weight=90 fixedInstance jres=icons.port2 //% whenUsed block="color 2" weight=90 fixedInstance jres=icons.port2

View File

@ -3,9 +3,9 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.color1.ambientLight() > 20) { if (sensors.color1.ambientLight() > 20) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -3,9 +3,9 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.color1.color() == ColorSensorColor.Green) { if (sensors.color1.color() == ColorSensorColor.Green) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -3,9 +3,9 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.color1.reflectedLight() > 20) { if (sensors.color1.reflectedLight() > 20) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -63,13 +63,13 @@
"control|block": "control", "control|block": "control",
"motors.Motor.angle|block": "%motor|angle", "motors.Motor.angle|block": "%motor|angle",
"motors.Motor.clearCounts|block": "%motor|clear counts", "motors.Motor.clearCounts|block": "%motor|clear counts",
"motors.Motor.setRegulated|block": "set %motor|regulated %value", "motors.Motor.setRegulated|block": "set %motor|regulated %value=toggleOnOff",
"motors.Motor.speed|block": "%motor|speed", "motors.Motor.speed|block": "%motor|speed",
"motors.Motor.tacho|block": "%motor|tacho", "motors.Motor.tacho|block": "%motor|tacho",
"motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready", "motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready",
"motors.MotorBase.reset|block": "%motors|reset", "motors.MotorBase.reset|block": "%motors|reset",
"motors.MotorBase.setBrake|block": "set %motor|brake %brake", "motors.MotorBase.setBrake|block": "set %motor|brake %brake=toggleOnOff",
"motors.MotorBase.setReversed|block": "set %motor|reversed %reversed", "motors.MotorBase.setReversed|block": "set %motor|reversed %reversed=toggleOnOff",
"motors.MotorBase.setSpeed|block": "set %motor|speed to %speed=motorSpeedPicker|%", "motors.MotorBase.setSpeed|block": "set %motor|speed to %speed=motorSpeedPicker|%",
"motors.MotorBase.stop|block": "%motors|stop", "motors.MotorBase.stop|block": "%motors|stop",
"motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio=motorTurnRatioPicker|speed %speed=motorSpeedPicker|%", "motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio=motorTurnRatioPicker|speed %speed=motorSpeedPicker|%",
@ -101,6 +101,7 @@
"{id:category}Motors": "Motors", "{id:category}Motors": "Motors",
"{id:category}Output": "Output", "{id:category}Output": "Output",
"{id:category}Screen": "Screen", "{id:category}Screen": "Screen",
"{id:category}Sensors": "Sensors",
"{id:category}Serial": "Serial", "{id:category}Serial": "Serial",
"{id:group}Buttons": "Buttons", "{id:group}Buttons": "Buttons",
"{id:group}Counters": "Counters", "{id:group}Counters": "Counters",

View File

@ -11,7 +11,7 @@ namespace sensors.internal {
// This is implementation for the simulator. // This is implementation for the simulator.
control.runInBackground(() => { control.runInParallel(() => {
let prev = query() let prev = query()
changeHandler(prev, prev) changeHandler(prev, prev)
while (true) { while (true) {
@ -196,83 +196,6 @@ 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;
public 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) {
if (this == null) return
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 { export class UartSensor extends Sensor {
protected mode: number // the mode user asked for protected mode: number // the mode user asked for
protected realmode: number // the mode the hardware is in protected realmode: number // the mode the hardware is in
@ -499,3 +422,83 @@ namespace sensors.internal {
TST_UART_WRITE = 0xc048740a, TST_UART_WRITE = 0xc048740a,
} }
} }
namespace sensors {
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;
public 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) {
if (this == null) return
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 {
const interval = (this.highThreshold - this.lowThreshold) / 6;
if ((this.state == ThresholdState.High && this.level < this.highThreshold - interval) ||
(this.state == ThresholdState.Low && this.level > this.lowThreshold + interval))
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;
}
}
}
}

View File

@ -271,7 +271,12 @@ void setupThread(Action a, TValue arg = 0, void (*runner)(Thread *) = NULL, TVal
} }
} }
void runInBackground(Action a) { void releaseFiber() {
stopUser();
pthread_exit(NULL);
}
void runInParallel(Action a) {
setupThread(a); setupThread(a);
} }

View File

@ -161,8 +161,7 @@ namespace motors {
* Sets the automatic brake on or off when the motor is off * Sets the automatic brake on or off when the motor is off
* @param brake a value indicating if the motor should break when off * @param brake a value indicating if the motor should break when off
*/ */
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake" //% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff"
//% brake.fieldEditor=toggleonoff
//% weight=60 blockGap=8 //% weight=60 blockGap=8
//% group="Move" //% group="Move"
setBrake(brake: boolean) { setBrake(brake: boolean) {
@ -173,8 +172,7 @@ namespace motors {
/** /**
* Reverses the motor polarity * Reverses the motor polarity
*/ */
//% blockId=motorSetReversed block="set %motor|reversed %reversed" //% blockId=motorSetReversed block="set %motor|reversed %reversed=toggleOnOff"
//% reversed.fieldEditor=toggleonoff
//% weight=59 blockGap=8 //% weight=59 blockGap=8
//% group="Move" //% group="Move"
setReversed(reversed: boolean) { setReversed(reversed: boolean) {
@ -193,6 +191,14 @@ namespace motors {
stop() { stop() {
this.init(); this.init();
stop(this._port, this._brake); stop(this._port, this._brake);
this.settle();
}
private settle() {
// if we've recently completed a motor command with brake
// allow 500ms for robot to settle
if(this._brake)
loops.pause(500);
} }
/** /**
@ -253,6 +259,8 @@ namespace motors {
this._move(useSteps, stepsOrTime, speed); this._move(useSteps, stepsOrTime, speed);
// wait till motor is done with this work // wait till motor is done with this work
this.pauseUntilReady(); this.pauseUntilReady();
// allow robot to settle
this.settle();
} }
/** /**
@ -327,8 +335,7 @@ namespace motors {
* Indicates if the motor speed should be regulated. Default is true. * Indicates if the motor speed should be regulated. Default is true.
* @param value true for regulated motor * @param value true for regulated motor
*/ */
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value" //% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
//% value.fieldEditor=toggleonoff
//% weight=58 //% weight=58
//% group="Move" //% group="Move"
setRegulated(value: boolean) { setRegulated(value: boolean) {

View File

@ -10,11 +10,11 @@
"base": "file:../base", "base": "file:../base",
"core": "file:../core", "core": "file:../core",
"music": "file:../music", "music": "file:../music",
"mood": "file:../mood",
"color-sensor": "file:../color-sensor", "color-sensor": "file:../color-sensor",
"touch-sensor": "file:../touch-sensor", "touch-sensor": "file:../touch-sensor",
"ultrasonic-sensor": "file:../ultrasonic-sensor", "ultrasonic-sensor": "file:../ultrasonic-sensor",
"gyro-sensor": "file:../gyro-sensor" "gyro-sensor": "file:../gyro-sensor",
"mood": "file:../mood"
}, },
"public": true "public": true
} }

View File

@ -138,12 +138,12 @@ namespace sensors {
//% fixedInstances //% fixedInstances
export class InfraredSensor extends internal.UartSensor { export class InfraredSensor extends internal.UartSensor {
private channel: IrRemoteChannel; private channel: IrRemoteChannel;
private proximityThreshold: sensors.internal.ThresholdDetector; private proximityThreshold: sensors.ThresholdDetector;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this.channel = IrRemoteChannel.Ch0 this.channel = IrRemoteChannel.Ch0
this.proximityThreshold = new sensors.internal.ThresholdDetector(this._id, 0, 100, 10, 90); this.proximityThreshold = new sensors.ThresholdDetector(this._id, 0, 100, 10, 90);
irButton(0) // make sure buttons array is initalized irButton(0) // make sure buttons array is initalized
// and set the mode, as otherwise button events won't work // and set the mode, as otherwise button events won't work

View File

@ -1,16 +1,17 @@
{ {
"brick.Mood": "A mood", "brick.Mood": "A mood",
"brick.Mood.show": "Shows the mood on the EV3", "brick.Mood.show": "Shows the mood on the EV3",
"brick.angry": "An angry mood", "brick.showMood": "Shows a mood",
"brick.awake": "A awake mood", "moods.angry": "An angry mood",
"brick.dizzy": "A dizzy mood", "moods.awake": "A awake mood",
"brick.knockedOut": "A knocked out mood", "moods.dizzy": "A dizzy mood",
"brick.love": "In love mood", "moods.knockedOut": "A knocked out mood",
"brick.middleLeft": "Looking around left", "moods.love": "In love mood",
"brick.middleRight": "Looking around right", "moods.middleLeft": "Looking around left",
"brick.neutral": "In a neutral mood", "moods.middleRight": "Looking around right",
"brick.sad": "A sad mood", "moods.neutral": "In a neutral mood",
"brick.sleeping": "A sleeping mood", "moods.sad": "A sad mood",
"brick.tired": "A tired mood", "moods.sleeping": "A sleeping mood",
"brick.winking": "In laughing mood" "moods.tired": "A tired mood",
"moods.winking": "In laughing mood"
} }

View File

@ -1,6 +1,8 @@
{ {
"brick.Mood.show|block": "show mood %mood=mood_image_picker", "brick.showMood|block": "show mood %mood=mood_image_picker",
"brick|block": "brick", "brick|block": "brick",
"moods|block": "moods",
"{id:category}Brick": "Brick", "{id:category}Brick": "Brick",
"{id:category}Moods": "Moods",
"{id:group}Screen": "Screen" "{id:group}Screen": "Screen"
} }

View File

@ -1,12 +1,23 @@
namespace brick { namespace brick {
/**
* Shows a mood
*/
//% weight=90
//% blockId=moodShow block="show mood %mood=mood_image_picker"
//% weight=101 group="Screen" blockGap=8
export function showMood(mood: Mood) {
if(mood)
mood.show();
}
/** /**
* A mood * A mood
*/ */
//% fixedInstances //% fixedInstances
export class Mood { export class Mood {
image: Image; private image: Image;
sound: Sound; private sound: Sound;
light: BrickLight; private light: BrickLight;
constructor(image: Image, sound: Sound, light: BrickLight) { constructor(image: Image, sound: Sound, light: BrickLight) {
this.image = image; this.image = image;
@ -17,14 +28,11 @@ namespace brick {
/** /**
* Shows the mood on the EV3 * Shows the mood on the EV3
*/ */
//% weight=90
//% blockId=moodShow block="show mood %mood=mood_image_picker"
//% weight=101 group="Screen" blockGap=8
show() { show() {
brick.setLight(this.light); brick.setLight(this.light);
brick.showImage(this.image); brick.showImage(this.image);
if (this.sound) music.playSoundEffectUntilDone(this.sound);
music.playSoundEffect(this.sound); loops.pause(20);
} }
} }
@ -39,77 +47,79 @@ namespace brick {
//% group="Screen" weight=0 blockHidden=1 //% group="Screen" weight=0 blockHidden=1
export function __moodImagePicker(mood: Mood): Mood { export function __moodImagePicker(mood: Mood): Mood {
return mood; return mood;
} }
}
namespace moods {
/** /**
* A sleeping mood * A sleeping mood
*/ */
//% fixedInstance jres=images.eyesSleeping //% fixedInstance jres=images.eyesSleeping
export const sleeping = new Mood(images.eyesSleeping, sounds.expressionsSnoring, BrickLight.OrangePulse); export const sleeping = new brick.Mood(images.eyesSleeping, sounds.expressionsSnoring, BrickLight.OrangePulse);
/** /**
* A awake mood * A awake mood
*/ */
//% fixedInstance jres=images.eyesAwake //% fixedInstance jres=images.eyesAwake
export const awake = new Mood(images.eyesAwake, sounds.informationActivate, BrickLight.Orange); export const awake = new brick.Mood(images.eyesAwake, sounds.informationActivate, BrickLight.Orange);
/** /**
* A tired mood * A tired mood
*/ */
//% fixedInstance jres=images.eyesTiredMiddle //% fixedInstance jres=images.eyesTiredMiddle
export const tired = new Mood(images.eyesTiredMiddle, sounds.expressionsSneezing, BrickLight.OrangeFlash); export const tired = new brick.Mood(images.eyesTiredMiddle, sounds.expressionsSneezing, BrickLight.OrangeFlash);
/** /**
* An angry mood * An angry mood
*/ */
//% fixedInstance jres=images.eyesAngry //% fixedInstance jres=images.eyesAngry
export const angry = new Mood(images.eyesAngry, sounds.animalsDogGrowl, BrickLight.RedPulse); export const angry = new brick.Mood(images.eyesAngry, sounds.animalsDogGrowl, BrickLight.RedPulse);
/** /**
* A sad mood * A sad mood
*/ */
//% fixedInstance jres=images.eyesTear //% fixedInstance jres=images.eyesTear
export const sad = new Mood(images.eyesTear, sounds.animalsDogWhine, BrickLight.Red); export const sad = new brick.Mood(images.eyesTear, sounds.animalsDogWhine, BrickLight.Red);
/** /**
* A dizzy mood * A dizzy mood
*/ */
//% fixedInstance jres=images.eyesDizzy //% fixedInstance jres=images.eyesDizzy
export const dizzy = new Mood(images.eyesDizzy, sounds.expressionsUhOh, BrickLight.OrangeFlash); export const dizzy = new brick.Mood(images.eyesDizzy, sounds.expressionsUhOh, BrickLight.OrangeFlash);
/** /**
* A knocked out mood * A knocked out mood
*/ */
//% fixedInstance jres=images.eyesKnockedOut //% fixedInstance jres=images.eyesKnockedOut
export const knockedOut = new Mood(images.eyesKnockedOut, sounds.informationError, BrickLight.RedFlash); export const knockedOut = new brick.Mood(images.eyesKnockedOut, sounds.informationError, BrickLight.RedFlash);
/** /**
* Looking around left * Looking around left
*/ */
//% fixedInstance jres=images.eyesMiddleLeft //% fixedInstance jres=images.eyesMiddleLeft
export const middleLeft = new Mood(images.eyesMiddleLeft, sounds.informationAnalyze, BrickLight.Off); export const middleLeft = new brick.Mood(images.eyesMiddleLeft, sounds.informationAnalyze, BrickLight.Off);
/** /**
* Looking around right * Looking around right
*/ */
//% fixedInstance jres=images.eyesMiddleRight //% fixedInstance jres=images.eyesMiddleRight
export const middleRight = new Mood(images.eyesMiddleRight, sounds.informationAnalyze, BrickLight.Off); export const middleRight = new brick.Mood(images.eyesMiddleRight, sounds.informationAnalyze, BrickLight.Off);
/** /**
* In love mood * In love mood
*/ */
//% fixedInstance jres=images.eyesLove //% fixedInstance jres=images.eyesLove
export const love = new Mood(images.eyesLove, sounds.expressionsMagicWand, BrickLight.GreenPulse); export const love = new brick.Mood(images.eyesLove, sounds.expressionsMagicWand, BrickLight.GreenPulse);
/** /**
* In laughing mood * In laughing mood
*/ */
//% fixedInstance jres=images.eyesWinking //% fixedInstance jres=images.eyesWinking
export const winking = new Mood(images.eyesWinking, sounds.expressionsLaughing1, BrickLight.GreenFlash); export const winking = new brick.Mood(images.eyesWinking, sounds.expressionsLaughing1, BrickLight.GreenFlash);
/** /**
* In a neutral mood * In a neutral mood
*/ */
//% fixedInstance jres=images.eyesNeutral //% fixedInstance jres=images.eyesNeutral
export const neutral = new Mood(images.eyesNeutral, undefined, BrickLight.Green); export const neutral = new brick.Mood(images.eyesNeutral, undefined, BrickLight.Green);
} }

View File

@ -9,6 +9,7 @@
], ],
"public": true, "public": true,
"dependencies": { "dependencies": {
"core": "file:../core" "core": "file:../core",
"music": "file:../music"
} }
} }

View File

@ -23,7 +23,7 @@
"music.setTempo": "Set the tempo a number of beats per minute (bpm).", "music.setTempo": "Set the tempo a number of beats per minute (bpm).",
"music.setTempo|param|bpm": "The new tempo in beats per minute, eg: 120", "music.setTempo|param|bpm": "The new tempo in beats per minute, eg: 120",
"music.setVolume": "Set the output volume of the sound synthesizer.", "music.setVolume": "Set the output volume of the sound synthesizer.",
"music.setVolume|param|volume": "the volume 0...256, eg: 128", "music.setVolume|param|volume": "the volume 0...100, eg: 50",
"music.stopAllSounds": "Play a tone through the speaker for some amount of time.", "music.stopAllSounds": "Play a tone through the speaker for some amount of time.",
"music.tempo": "Return the tempo in beats per minute (bpm).\nTempo is the speed (bpm = beats per minute) at which notes play. The larger the tempo value, the faster the notes will play." "music.tempo": "Return the tempo in beats per minute (bpm).\nTempo is the speed (bpm = beats per minute) at which notes play. The larger the tempo value, the faster the notes will play."
} }

View File

@ -13,7 +13,7 @@
namespace music { namespace music {
uint8_t currVolume = 2; uint8_t currVolume = 50;
uint8_t *lmsSoundMMap; uint8_t *lmsSoundMMap;
int writeDev(void *data, int size) { int writeDev(void *data, int size) {
@ -25,16 +25,16 @@ int writeDev(void *data, int size) {
/** /**
* Set the output volume of the sound synthesizer. * Set the output volume of the sound synthesizer.
* @param volume the volume 0...256, eg: 128 * @param volume the volume 0...100, eg: 50
*/ */
//% weight=96 //% weight=96
//% blockId=synth_set_volume block="set volume %volume" //% blockId=synth_set_volume block="set volume %volume"
//% parts="speaker" blockGap=8 //% parts="speaker" blockGap=8
//% volume.min=0 volume.max=256 //% volume.min=0 volume.max=100
//% help=music/set-volume //% help=music/set-volume
//% weight=1 //% weight=1
void setVolume(int volume) { void setVolume(int volume) {
currVolume = max(0, min(100, volume * 100 / 256)); currVolume = max(0, min(100, volume));
} }
#define SOUND_CMD_BREAK 0 #define SOUND_CMD_BREAK 0

View File

@ -3,12 +3,12 @@ declare namespace music {
/** /**
* Set the output volume of the sound synthesizer. * Set the output volume of the sound synthesizer.
* @param volume the volume 0...256, eg: 128 * @param volume the volume 0...100, eg: 50
*/ */
//% weight=96 //% weight=96
//% blockId=synth_set_volume block="set volume %volume" //% blockId=synth_set_volume block="set volume %volume"
//% parts="speaker" blockGap=8 //% parts="speaker" blockGap=8
//% volume.min=0 volume.max=256 //% volume.min=0 volume.max=100
//% help=music/set-volume //% help=music/set-volume
//% weight=1 shim=music::setVolume //% weight=1 shim=music::setVolume
function setVolume(volume: int32): void; function setVolume(volume: int32): void;

View File

@ -291,6 +291,9 @@ namespace music {
export function playSoundEffect(sound: Sound) { export function playSoundEffect(sound: Sound) {
if (!sound || numSoundsPlaying >= soundsLimit) return; if (!sound || numSoundsPlaying >= soundsLimit) return;
numSoundsPlaying++; numSoundsPlaying++;
control.runInBackground(() => {sound.play(); numSoundsPlaying--;}); control.runInParallel(() => {
sound.play();
numSoundsPlaying--;
});
} }
} }

View File

@ -1,11 +1,11 @@
# Touch Sensor # Touch Sensor
```cards ```cards
sensors.touchSensor1.onEvent(TouchSensorEvent.Pressed, function () { sensors.touch1.onEvent(TouchSensorEvent.Pressed, function () {
brick.showImage(images.expressionsBigSmile) brick.showImage(images.expressionsBigSmile)
}) })
sensors.touchSensor1.isPressed(); sensors.touch1.isPressed();
sensors.touchSensor1.wasPressed(); sensors.touch1.wasPressed();
``` ```
## See Also ## See Also

View File

@ -2,10 +2,10 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.touchSensor1.isPressed()) { if (sensors.touch1.isPressed()) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -1,7 +1,7 @@
# On Event # On Event
```sig ```sig
sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { }) sensors.touch1.onEvent(TouchSensorEvent.Released, function () { })
``` ```
# Parameters # Parameters
@ -10,7 +10,7 @@ sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { })
```blocks ```blocks
sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { sensors.touch1.onEvent(TouchSensorEvent.Released, function () {
brick.showImage(images.expressionsSick) brick.showImage(images.expressionsSick)
}) })
``` ```

View File

@ -2,10 +2,10 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.touchSensor1.wasPressed()) { if (sensors.touch1.wasPressed()) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -2,21 +2,21 @@ enum UltrasonicSensorEvent {
//% block="object detected" //% block="object detected"
ObjectDetected = 10, ObjectDetected = 10,
//% block="object near" //% block="object near"
ObjectNear = sensors.internal.ThresholdState.Low, ObjectNear = sensors.ThresholdState.Low,
//% block="object far" //% block="object far"
ObjectFar = sensors.internal.ThresholdState.High ObjectFar = sensors.ThresholdState.High
} }
namespace sensors { namespace sensors {
//% fixedInstances //% fixedInstances
export class UltraSonicSensor extends internal.UartSensor { export class UltraSonicSensor extends internal.UartSensor {
private promixityThreshold: sensors.internal.ThresholdDetector; private promixityThreshold: sensors.ThresholdDetector;
private movementThreshold: number; private movementThreshold: number;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this.promixityThreshold = new sensors.internal.ThresholdDetector(this.id(), 0, 255, 10, 100); // range is 0..255cm this.promixityThreshold = new sensors.ThresholdDetector(this.id(), 0, 255, 10, 100); // range is 0..255cm
this.movementThreshold = 1; this.movementThreshold = 1;
} }

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.0.64", "version": "0.0.73",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.0.68", "version": "0.0.73",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode", "description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true, "private": true,
"keywords": [ "keywords": [
@ -44,8 +44,8 @@
"webfonts-generator": "^0.4.0" "webfonts-generator": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "0.15.6", "pxt-common-packages": "0.17.11",
"pxt-core": "3.0.11" "pxt-core": "3.0.25"
}, },
"scripts": { "scripts": {
"test": "node node_modules/pxt-core/built/pxt.js travis" "test": "node node_modules/pxt-core/built/pxt.js travis"

View File

@ -21,7 +21,7 @@
"libs/storage", "libs/storage",
"libs/datalog", "libs/datalog",
"libs/tests", "libs/tests",
"libs/behaviors" "libs/automation"
], ],
"simulator": { "simulator": {
"autoRun": true, "autoRun": true,

View File

@ -16,25 +16,8 @@ namespace pxsim.SoundMethods {
return incr(buf) return incr(buf)
} }
export function uint8ArrayToString(input: Uint8Array) { export function play(buf: RefBuffer) {
let len = input.length; return pxsim.AudioContextManager.playBufferAsync(buf);
let res = ""
for (let i = 0; i < len; ++i)
res += String.fromCharCode(input[i]);
return res;
}
export function play(buf: RefBuffer, volume: number) {
if (!buf) {
return Promise.resolve();
}
return new Promise<void>(resolve => {
let url = "data:audio/wav;base64," + btoa(uint8ArrayToString(buf.data))
audio = new Audio(url)
audio.onended = () => resolve();
audio.onpause = () => resolve();
audio.play();
})
} }
export function stop() { export function stop() {

View File

@ -9,6 +9,7 @@
}, },
"galleries": { "galleries": {
"Maker Activities": "maker", "Maker Activities": "maker",
"Coding Activites": "coding" "Coding Activites": "coding",
"Lessons": "lessons"
} }
} }

View File

@ -111,4 +111,19 @@
.sandboxfooter a:not(.thin) { .sandboxfooter a:not(.thin) {
color: @black !important; color: @black !important;
} }
}
/** high contrast **/
.hc {
.ui.menu, #downloadArea,
.menubar .ui.menu.fixed .ui.item.editor-menuitem .item.active {
background-color: black !important;
color: white !important;
}
.ui.red.corner.label {
border-color: #d4000d!important;
}
.menubar .ui.menu.fixed .item.editor-menuitem .ui.grid {
border-color: white !important;
}
} }