Microsoft MakeCode

Event Handler Blocks

Hello,

I am an FRC mentor, and we just purchased the Freenove micro:bit mini rover. It is a wonderful device. I am trying to figure out if it is feasible to create a custom interface to teach students how to program using WPILib conventions. This will allow students to use this robot to learn how to program a robot with FRC-like syntax in drag and drop programming.

The basic structure I am looking to create is…

When the robot starts > Do…

Periodically when the robot is running > Do…

When in Autonomous mode > Do…

When in teleoperated mode >Do…

My question is, I do not know how to create a block that wraps (like the forever blocks), and will run once on an event is triggered (or periodically while an event triggered state is true).

I am not incredibly familiar with javascript/typescript, and most of the general event handler docs are either way too specific or way too general for me to apply to this context.

See the attached image for what I would like students to see.

Any help you could give or docs you could send me to would be appreciated.

Hi mrRSquared,

The easiest way is something like this inside a namespace:

//% block="Do something"
export function onYourEvent(codeToFire: () => void): void {
  
}

image
Then somewhere hidden in your code just call that function based on a timer etc. Does that make sense? Start with the custom.ts file to explore.

Thanks,
Josh

1 Like

Thank you. That makes sense, and I figured that part out, but I cannot figure out the next step. There are a few pieces here.
First, if I do as above,

   
    //% block="Do something"
export function onYourEvent(codeToFire: () => void): void {
  
}

Then try to call it, the engine adds a lot to the method call. Let’s say I want to loop it without blocking…

basic.forever(function () {onYourEvent(function () {
        
    });//it adds the argument (function(){})
	
})

When I run it with inputs like so…
image

The screen always shows zero.
If I modify it to the following, I can get it to increase to one, but not increase continuously (which is what I expected.

//% block="Do something"
export function onYourEvent(codeToFire: () => void): void {
    codeToFire();
}

basic.forever(function () {onYourEvent(function () {   
    });	
})

So, how do I call that function so that it runs each time it is called? I will work up the framework with the timer later tonight, but basically, I want to make a thread that is the Robot scheduler. It will loop every 20ms. If the mode has not changed, it would just run robotPeriodic(), then the loop (auto or tele), if it had changed, it will run the init() function first.

Thank you for your help. If this works, I feel it will be an incredible educational tool.

Hi again,

So I think I know what you’re asking. I don’t have a lot of time tonight, but here is a quick example I wrote up and tested in the simulator. The first part I wrote in custom.ts:

/** * Custom blocks */ //% weight=100 color=#0fbc11 icon="" namespace custom {
let nextEvent1Time = 0

let EVENT1_PERIOD = 5000 // Fire every 5 seconds

let EVENT2_PERIOD = 3000 // Fire every 3 seconds

let Event1Fire: (params: any) => void
let Event2Fire: (params: any) => void

//% block="Event1"
export function Event1(codeToFire: () => void): void {
  Event1Fire = codeToFire
}

 
//% block="Event2"
export function Event2(codeToFire: () => void): void {
  Event2Fire = codeToFire
}

basic.forever(function () { //Let's keep a forever loop running inside our custom namespace. You could probably at a basic.pause at the bottom of the loop to slow down how fast it runs.

let nextEvent2Time = 0

if (input.runningTime() > nextEvent1Time) {

    Event1Fire(null) //Fire the code
    nextEvent1Time = input.runningTime() + EVENT1_PERIOD //Set the next timer event
}

if (input.runningTime() > nextEvent2Time) {

    Event2Fire(null) //Fire the code
    nextEvent2Time = input.runningTime() + EVENT2_PERIOD //Set the next timer event
}

})
}

The next part would go in your main.ts

custom.Event2(function () {
basic.showIcon(IconNames.Butterfly)
})
custom.Event1(function () {
basic.showIcon(IconNames.Heart)
})

So every 3 seconds Event2 code is called and every 5 seconds Event1 code is called.

Let me know if that is what you are looking for.

1 Like

Woot!!!
That is exactly what I am looking for. I will post an iteration when I get a chance, but this worked, and I can see how I will easily be able to apply it to our context. This is incredible.
~MrR^2

Hello again,
Here is the current version of our code. We put everything in custom.ts for now, but It works exactly as expected. Thank you again.

~Mr.R^2

Hello, So, I am making a lot of progress. I want to streamline it a bit, but I am struggling to understand how the variables interact. What I would like is one block that uses an enum value to switch between the different functions. That way, the students will not have to sort through multiple blocks that do the same thing. Here is what I am looking for. I am wondering how to make it work so that changing the event variable changes the function.

image

I figured out one way to accomplish this pretty easily. You can pass the argument into the method and it does not seem to get hung up on multiple instances…

enum MyEnum {
    //% block="teleopPeriodic()"
    TelePeriodic,
    //% block="autoPeriodic()"
    AutoPeriodic
}
//% block="on $arg"
        export function teleopPeriodic(arg: MyEnum, a: () => void): void {
                if (arg == 0){
                TelePeriodic = a; }
                else {
                    AutoPeriodic = a
                }        
        }