Greetings!
This project’s goal was to:
The result is this program:
let delay = 0
let FirstRun = 1
// Button "A" starts the micro:bot moving
// Button "A+B" enters/exits change delay mode
input.onButtonPressed(Button.A, function () {
motobit.enable(MotorPower.Off)
motobit.setMotorSpeed(Motor.Left, MotorDirection.Forward, 50)
motobit.setMotorSpeed(Motor.Right, MotorDirection.Forward, 50)
motobit.enable(MotorPower.On)
basic.pause(1000)
motobit.enable(MotorPower.Off)
basic.pause(1000) // stop before making turn
motobit.setMotorSpeed(Motor.Left, MotorDirection.Reverse, 50)
motobit.setMotorSpeed(Motor.Right, MotorDirection.Forward, 50)
motobit.enable(MotorPower.On)
basic.pause(delay)
motobit.enable(MotorPower.Off)
basic.pause(1000) // stop before moving back again
motobit.setMotorSpeed(Motor.Left, MotorDirection.Forward, 50)
motobit.setMotorSpeed(Motor.Right, MotorDirection.Forward, 50)
motobit.enable(MotorPower.On)
basic.pause(1000)
motobit.enable(MotorPower.Off)
})
input.onButtonPressed(Button.AB, function () {
SetDelay()
basic.showString("A=Start")
})
// Function SetDelay allows the length of the turn to be adjusted
// while the device is being used, without having to re-download
// corrected values - i.e. /in vivo/ results.
function SetDelay() {
basic.showString("Set Delay")
// FirstRun detects if this is the first time the delay adjust
// has been called, if so, display instructions
if (FirstRun == 1) {
basic.showString("A=- B=+")
basic.showString("A+B=Exit")
FirstRun = 0
}
// Button "A" subtracts 50 ms from the turn time
// Button "B" adds 50 ms to the turn time
// Button "A+B" exits and returns to "run" mode
while (true) {
if (input.buttonIsPressed(Button.A)) {
delay += -50
}
if (input.buttonIsPressed(Button.B)) {
delay += 50
}
if (input.buttonIsPressed(Button.AB)) {
basic.showString("Exit")
return
}
basic.showNumber(delay)
basic.showString("*")
}
}
motobit.invert(Motor.Left, false)
motobit.invert(Motor.Right, false)
delay = 700
basic.showString("A=Start")
basic.showString("A+B=Change Delay")
The first part is the top couple of lines, and the lines at the very bottom:
let delay = 0
let FirstRun = 1
. . . . . .
motobit.invert(Motor.Left, false)
motobit.invert(Motor.Right, false)
delay = 700
basic.showString("A=Start")
basic.showString("A+B=Change Delay")
This initializes the two local variables, “delay” (the amount of the radial delay in milliseconds) and FirstRun, a flag to indicate if the SetDelay function should display instructions, since it displays instructions only when run the first time.
Note that I could get rid of the one line of code “delay = 700” by pre-setting it at the top of the program. I already did that with FirstRun.
This is the part of the program that actually moves the micro:bot.
// Button "A" starts the micro:bot moving
// Button "A+B" enters/exits change delay mode
input.onButtonPressed(Button.A, function () {
motobit.enable(MotorPower.Off)
motobit.setMotorSpeed(Motor.Left, MotorDirection.Forward, 50)
motobit.setMotorSpeed(Motor.Right, MotorDirection.Forward, 50)
motobit.enable(MotorPower.On)
basic.pause(1000)
motobit.enable(MotorPower.Off)
basic.pause(1000) // stop before making turn
motobit.setMotorSpeed(Motor.Left, MotorDirection.Reverse, 50)
motobit.setMotorSpeed(Motor.Right, MotorDirection.Forward, 50)
motobit.enable(MotorPower.On)
basic.pause(delay)
motobit.enable(MotorPower.Off)
basic.pause(1000) // stop before moving back again
motobit.setMotorSpeed(Motor.Left, MotorDirection.Forward, 50)
motobit.setMotorSpeed(Motor.Right, MotorDirection.Forward, 50)
motobit.enable(MotorPower.On)
basic.pause(1000)
motobit.enable(MotorPower.Off)
})
Button “A” starts this section when pressed which is a very valuable technique that I saw in some of the exercises. Waiting for a button press allows whoever’s playing with the 'bot to put it down and get it ready before launching it. It’s also safer that way.
Once started this routine:
input.onButtonPressed(Button.AB, function () {
SetDelay()
basic.showString("A=Start")
})
This detects the A+B button press and calls SetDelay().
Note that up to this point, all the button actions have been top-level button events using the “On Button [A]” or [A+B] button handler events. Once the SetDelay function starts the meaning and operation of the buttons can change.
/ Function SetDelay allows the length of the turn to be adjusted
// while the device is being used, without having to re-download
// corrected values - i.e. /in vivo/ results.
function SetDelay() {
basic.showString("Set Delay")
// FirstRun detects if this is the first time the delay adjust
// has been called, if so, display instructions
if (FirstRun == 1) {
basic.showString("A=- B=+")
basic.showString("A+B=Exit")
FirstRun = 0
}
// Button "A" subtracts 50 ms from the turn time
// Button "B" adds 50 ms to the turn time
// Button "A+B" exits and returns to "run" mode
while (true) {
if (input.buttonIsPressed(Button.A)) {
delay += -50
}
if (input.buttonIsPressed(Button.B)) {
delay += 50
}
if (input.buttonIsPressed(Button.AB)) {
basic.showString("Exit")
return
}
basic.showNumber(delay)
basic.showString("*")
}
}
Here, the behavior of the A, B, and A+B button actions change. It also introduces the concept of “modes” of operation.
As mentioned before, the variable FirstRun is a simple toggle to detect if the operator has already seen the instructions. If so, don’t bother showing them again. (a good programming practice)
Here’s where the action is:
// Button "A" subtracts 50 ms from the turn time
// Button "B" adds 50 ms to the turn time
// Button "A+B" exits and returns to "run" mode
while (true) {
if (input.buttonIsPressed(Button.A)) {
delay += -50
}
if (input.buttonIsPressed(Button.B)) {
delay += 50
}
if (input.buttonIsPressed(Button.AB)) {
basic.showString("Exit")
return
}
basic.showNumber(delay)
basic.showString("*")
}
This detects the button presses inside the function. Note that the function “traps” the button presses and prevents them from being passed to the generic button-press handlers at the top level of the code. Note also that, because we can trap the button events, we can use them to do whatever we want.
Additionally, note the “return” statement at the bottom. This is not a statement included in the blockly programming interface within MakeCode, (though it should be).
Note also that this part of the code could have been implemented with an “if - elseif - else” or a “switch-case” block. Note that, like the “return” statement, “switch-case” is legal JavaScript and can be used here, but it must be entered by hand.
The “while (true)” block sets up an endless loop that is used to poll for button presses inside the function. Since this will never exit, the return statement is used to jump out once the A+B button press is detected.
The function of this section is like this:
Once this function has exited, control of the buttons returns to the top-level button event handlers. The board prints “A to start” and waits for the user to press the “A” button to launch the robot.
At this point, we’re back to where we started at the beginning except that the delay variable for the turn has been changed.
Comments and suggestions are always welcome.
Jim “JR”