Part Six: The End, and the Beginning

Well, I hope you did your homework because it’s the last you’ll get in this series. We’ve talked about what Myo Scripts are, walked you through your first one, detected poses, done keyboard input, and handled vibration and locking. Today, we’ll finish off with (most of) the other callbacks, and give you the completed script.

But first, the solution from last time:

  


if (pose ~= "rest" and pose ~= "unknown") then
            -- hold if edge is on, timed if edge is off
            myo.unlock(edge == "off" and "timed" or "hold")
        end  

Recognize that? I hope so, it’s the technique I mentioned last time. On any pose except rest and unknown, if edge is off call myo.unlock(“timed”), otherwise call myo.unlock(“hold”). Again you could have done it with an If block or a function, but this is the most concise.

Comments are the other thing to note. If you haven’t seen them before, you can comment a line in Lua with two dashes (). This means the line won’t get executed, so it’s good for leaving notes for yourself or temporarily disabling parts of your code you may want to re-enable later.

The Penultimate Callbacks

We’ll go into the last callback, onPeriodic, in the next tutorial series, but before that let’s briefly discuss the other two we haven’t talked about yet: activeAppNameonActiveChange(isActive), onLock and onUnlock.  activeAppName is called when Myo Connect wants to know what app your script is CURRENTLY controlling. All you really need to do for this is to store the app title you get from onForegroundWindowChange when you detect an app you want to control, and return it in activeAppName(). You can also return scriptTitle if it’s the same name as the application and you only control one.

'onActiveChange' is even easier. You probably don’t even need to implement it. The idea is it will get called with false when your script is not longer active. If there is any cleanup you need to do at that point, this is where you put it. You probably won’t have any though. This function also gets called with true when your script becomes active, but since you triggered that in onForegroundWindowChange you can do whatever setup you need in there.

onLock and onUnlock are pretty straightforward as well. If you need to do something when the armband is locked or unlocked, do it in there. If you want to create a script where the armband is unlocked with double tap and then not locked again until the user double taps again (like for a mouse control script or something), you would implement onUnlock so it calls myo.unlock(“hold”) (and turns on the mouse):

  


function onUnlock()  
        myo.unlock("hold")
        myo.controlMouse(true)
    end  

We’ll talk about mouse control more in the next tutorial.

Try modifying onForegroundWindowChange and implementing activeAppName. We’re not going to use onActiveChange or onLock/onUnlock.

For our simple script that tries to control everything, mine looks like this:

  


appTitle = ""

    function onForegroundWindowChange(app, title)  
        myo.debug("onForegroundWindowChange: " .. app .. ", " .. title)
        appTitle = title
        return true
    end

    function activeAppName()  
        return appTitle
    end  

The Completed Script

And that’s it. Your finished script should look something like this:

  


scriptId = 'com.thalmic.examples.myfirstscript'  
    scriptTitle = "My First Script"  
    scriptDetailsUrl = ""

    locked = true  
    appTitle = ""

    function onForegroundWindowChange(app, title)  
        myo.debug("onForegroundWindowChange: " .. app .. ", " .. title)
        appTitle = title
        return true
    end

    function activeAppName()  
        return appTitle
    end

    function onPoseEdge(pose, edge)  
        myo.debug("onPoseEdge: " .. pose .. ": " .. edge)

        pose = conditionallySwapWave(pose)

        if (pose ~= "rest" and pose ~= "unknown") then
            -- hold if edge is on, timed if edge is off
            myo.unlock(edge == "off" and "timed" or "hold")
        end

        local keyEdge = edge == "off" and "up" or "down"

        if (pose == "waveOut") then
            onWaveOut(keyEdge)      
        elseif (pose == "waveIn") then
            onWaveIn(keyEdge)
        elseif (pose == "fist") then
            onFist(keyEdge)
        elseif (pose == "fingersSpread") then
            onFingersSpread(keyEdge)            
        end
    end

    function onWaveOut(keyEdge)  
        myo.debug("Next")
        --myo.vibrate("short")
        myo.keyboard("tab", keyEdge)
    end

    function onWaveIn(keyEdge)  
        myo.debug("Previous")
        --myo.vibrate("short")
        --myo.vibrate("short")
        myo.keyboard("tab",keyEdge,"shift")
    end

    function onFist(keyEdge)  
        myo.debug("Enter")  
        --myo.vibrate("medium")
        myo.keyboard("return",keyEdge)
    end

    function onFingersSpread(keyEdge)  
        myo.debug("Escape")
        --myo.vibrate("long")
        myo.keyboard("escape", keyEdge)
    end

    function conditionallySwapWave(pose)  
        if myo.getArm() == "left" then
            if pose == "waveIn" then
                pose = "waveOut"
            elseif pose == "waveOut" then
                pose = "waveIn"
            end
        end
        return pose
    end  

It’s pretty basic, but shows you how to do key things like print to the debug console and press certain keys in response to specific poses. That’s all  you need to Myo-enable a lot of interesting apps.

One thing to note is that, while these scripts are written in Lua, the final version should have a .myo extension. This will let users double click on them to have them automatically loaded into the Application Manager. The downside of this is if you try and edit a .myo file it won’t have any of that nice pretty syntax highlighting without a bit of work. In Notepad++, you can go to Settings -> Style Configurator and add .myo as a user filetype for Lua.

Our next tutorial is going to target a specific game (Race The Sun, if you’re curious) and show you how to use onPeriodic and the IMU, which opens up even more possibilities. Until then, get scripting, and good luck! If you have any questions post them in the Developer Forums, or hit me up on Twitter at @thalmicdev!

Newsletter

Enter your email address and get all latest content delivered to your inbox every now and then.