North (formerly Thalmic Labs), the creator of the Myo armband, was acquired by Google in June 2020. Myo sales ended in October 2018 and Myo software, hardware and SDKs are no longer available or supported. Learn more.
Hello! Welcome to a new series I like to call #MyoCraft. I’ll be coming at you once a week (every weekend) with a neat script, code snippet, or cool project built for the Myo armband. Sometimes it’ll be an awesome script that’s just a bit too raw for general use. Other times, we’ll have a useful technique or a bit of best practice. Or maybe it will require a custom hardware hack. Whatever! We’ve made some sweet things around Thalmic Labs that we’d like to show off, but you’ve been working on something that seems like it would be a good fit, let me know on Twitter at @thalmicdev, or at by email at MyoCraft@thalmic.com. We’d love to highlight all the great things our community has come up with.
Here’s the script:
scriptId = 'com.jakechapeskie.media' minMyoConnectVersion ='0.8.1' scriptDetailsUrl = 'https://github.com/JakeChapeskie/MyoScripts' scriptTitle = 'Media Keys' ROLL_MOTION_THRESHOLD = 7 -- degrees SLOW_MOVE_PERIOD = 20 rollReference=0 moveSince=0 enabled=false myo.setLockingPolicy("standard") function onForegroundWindowChange(app, title) return true end function getMyoRollDegrees() local RollValue = math.deg(myo.getRoll()) return RollValue end function onUnlock() enabled=false end function degreeDiff(value, base) local diff = value - base if diff > 180 then diff = diff - 360 elseif diff < -180 then diff = diff + 360 end return diff 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 function onPoseEdge(pose, edge) pose=conditionallySwapWave(pose) local now = myo.getTimeMilliseconds() --Hold to activate if edge == "on" then if pose == "fist" then moveActive = edge == "on" rollReference = getMyoRollDegrees() moveSince = now enabled=true elseif pose =="waveIn" then myo.mediaKey("previous") elseif pose =="waveOut" then myo.mediaKey("next") elseif pose =="fingersSpread" then myo.mediaKey("play_pause") else enabled=false end end end function onPeriodic() local now = myo.getTimeMilliseconds() if (myo.isUnlocked()) and enabled then local relativeRoll = degreeDiff(getMyoRollDegrees(), rollReference) if math.abs(relativeRoll)> ROLL_MOTION_THRESHOLD then if now - moveSince > SLOW_MOVE_PERIOD then if relativeRoll>0 then myo.mediaKey("volume_up") else myo.mediaKey("volume_down") end moveSince = now end end end end
The key is this new function: myo.mediaKey(keyName). It lets you trigger any of those special media keys some keyboards have right from Myo Script.
That means you could use your Myo armband to control ANY media application that listens for those keys! And it doesn’t have to be in the foreground!
That’s pretty sweet, but there is a slight hiccup. For a script to be active when the application it controls is not in the foreground, it basically needs to be active all the time. That’s this block here:
function onForegroundWindowChange(app, title) return true end
To use this script, you need to make sure it’s on the BOTTOM of your application manager. It will start there, but it also needs to STAY THERE. The way Myo Connect works is that it asks each script in the Application Manager, from top to bottom, if it wants to be active or not. The first one that returns true gets it. Since this script always returns true, nothing below it could ever possibly become active.
So, any time you install a new connector you need to make sure you go in and move it up above this one or it won’t work. Obviously that’s not ideal, and we’re working on solutions, but for now that’s how it is. Don’t forget!
You can grab the completed script here.
That’s it for #MyoCraft this week! See you next Saturday!