-
Oh, that's awesome!
Is this the one? Or am I getting ahead of myself? π
edit: I did get ahead of myself - found it https://github.com/espruino/EspruinoDocs/blob/master/modules/USBMedia.js
-
I think I can safely say this is the tiniest bit of soldering I've ever done!
All glued up now, and still works when I plug it back in.> > ____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |____|___| _|_| |___|_|_|_|___| |_| espruino.com 2v09 (c) 2021 G.Williams > Connecting to WiFi Connected Response: httpCRs: { "hdrs": true, "headers": { "Date": "Tue, 06 Jul 2021 16:53:51 GMT", "Server": "Apache/2.4.18 (Ubuntu)", "Last-Modified": "Fri, 15 Nov 2013 15:42:26 GMT", "ETag": "\"d-4eb390b887c80\"", "Accept-Ranges": "bytes", "Content-Length": "13", "Connection": "close", "Content-Type": "text/plain" }, "cRcv": 0, "httpVersion": "1.1", "statusCode": "200", "statusMessage": "OK" } --->Hello World! >
I'm chuffed to bits. Many thanks again for the help Gordon!
Now I will be able to make my IR remote control do more than just control the media buttons on my PC :-)
-
-
I DID IT!
There was a tiny nub left under the lifted pad that I anchored a tiny wire to using solder paste, and then the bit of flappy trace on the other side of the pad was just able to be soldered to, it looks like a mess but I can happily say I managed to upload the firmware and run your example code!
When I get to glueing it all down (yep, gonna get the UV-cure resin out!) I'll send a picture for fun so you can see just how much I butchered my lovely little shim! π haha
-
-
-
-
Oh dear, it was all going so well!
I was following the tutorial for installing the Pico WiFi Shim, and found it difficult to solder the three pins that are close together - the ones you need a little bit of solid-core wire to link them.
I believe I have a short between the shim and the Pico where solder has bled through, but wanted to confirm, should the pins indicated in red share a connection? or have I borked it?
-
-
Final working code:
let debug = 0; let code = 0; let timeout; let lastTime; const VOLUME_UP = 16712445; const VOLUME_DOWN = 16750695; const PLAY_PAUSE = 16754775; const MUTE = 16720605; const NEXT = 16748655; const PREV = 16769055; const STOP = 16756815; E.setUSBHID({ reportDescriptor : [ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) 0x09, 0x01, // USAGE (Consumer Control) 0xa1, 0x01, // COLLECTION (Application) // -------------------- common global items 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) - each field occupies 1 bit // -------------------- misc bits 0x95, 0x05, // REPORT_COUNT (5) 0x09, 0xb5, // USAGE (Scan Next Track) 0x09, 0xb6, // USAGE (Scan Previous Track) 0x09, 0xb7, // USAGE (Stop) 0x09, 0xcd, // USAGE (Play/Pause) 0x09, 0xe2, // USAGE (Mute) 0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs // -------------------- volume up/down bits 0x95, 0x02, // REPORT_COUNT (2) 0x09, 0xe9, // USAGE (Volume Up) 0x09, 0xea, // USAGE (Volume Down) 0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs // -------------------- padding bit 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0xc0 // END_COLLECTION ] }); function p(c, cb) { E.sendUSBHID([c]); setTimeout(function() { E.sendUSBHID([0]); cb(); },100); } next = function (cb) { p(0x1, cb); console.log('next'); }; prev = function (cb) { p(0x2, cb); console.log('prev'); }; stop = function (cb) { p(0x4, cb); console.log('stop'); }; playpause = function (cb) { p(0x8, cb); console.log('playpause'); }; mute = function (cb) { p(0x10, cb); console.log('mute'); }; volumeUp = function (cb) { p(0x20, cb); console.log('volumeUp'); }; volumeDown = function (cb) { p(0x40, cb); console.log('volumeDown'); }; const cb = () => {}; function handleCode() { timeout = undefined; if (debug) print(code); LED2.write(true); if (code === PLAY_PAUSE) playpause(cb); if (code === VOLUME_UP) volumeUp(cb); if (code === VOLUME_DOWN) volumeDown(cb); if (code === MUTE) mute(cb); if (code === NEXT) next(cb); if (code === PREV) prev(cb); if (code === STOP) stop(cb); code = 0; LED2.write(false); } // When an IR pulse is detected function onPulseOn(e) { code = (code * 2) | (e.time - lastTime > 0.0008); if (timeout !== undefined) clearTimeout(timeout); timeout = setTimeout(handleCode, 20); lastTime = e.time; } // When IR pulse stops function onPulseOff(e) { lastTime = e.time; } setWatch(onPulseOff, A5, { repeat: true, edge: "rising" }); setWatch(onPulseOn, A5, { repeat: true, edge: "falling" }); setWatch( // Press the button on the pico to enable debug mode and // see the IR code for your own remote function (e) { debug = !debug; console.log(`Debug mode ${debug ? "on" : "off"}`); }, BTN, { repeat: true } );
-
Hmm - when pressing keys normally on the keyboard, you send one HID report for keydown, and another to show the key has been lifted. It didn't seem to be the case on the BLE version but maybe you need to do that here?
Yep that was exactly it!
Thanks for the snippet Gordon, simply dropped it in and now it's working brilliantly.
I think a module for this would have definitely helped me in the first instance.
-
-
Here's the latest incarnation! Working pretty well.
Sometimes the mute and playpause commands don't work the 2nd time you press them, but with subsequent presses work fine
let debug = 0; let code = 0; let timeout; let lastTime; const VOLUME_UP = 16712445; const VOLUME_DOWN = 16750695; const PLAY_PAUSE = 16754775; const MUTE = 16720605; const NEXT = 16748655; const PREV = 16769055; const STOP = 16756815; E.setUSBHID({ reportDescriptor : [ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) 0x09, 0x01, // USAGE (Consumer Control) 0xa1, 0x01, // COLLECTION (Application) // -------------------- common global items 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) - each field occupies 1 bit // -------------------- misc bits 0x95, 0x05, // REPORT_COUNT (5) 0x09, 0xb5, // USAGE (Scan Next Track) 0x09, 0xb6, // USAGE (Scan Previous Track) 0x09, 0xb7, // USAGE (Stop) 0x09, 0xcd, // USAGE (Play/Pause) 0x09, 0xe2, // USAGE (Mute) 0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs // -------------------- volume up/down bits 0x95, 0x02, // REPORT_COUNT (2) 0x09, 0xe9, // USAGE (Volume Up) 0x09, 0xea, // USAGE (Volume Down) 0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs // -------------------- padding bit 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0xc0 // END_COLLECTION ] }); function p(c, cb) { E.sendUSBHID([c]); return cb(); } next = function (cb) { p(0x1, cb); console.log('next'); }; prev = function (cb) { p(0x2, cb); console.log('prev'); }; stop = function (cb) { p(0x4, cb); console.log('stop'); }; playpause = function (cb) { p(0x8, cb); console.log('playpause'); }; mute = function (cb) { p(0x10, cb); console.log('mute'); }; volumeUp = function (cb) { p(0x20, cb); console.log('volumeUp'); }; volumeDown = function (cb) { p(0x40, cb); console.log('volumeDown'); }; const cb = () => {}; function handleCode() { timeout = undefined; if (debug) print(code); LED2.write(true); if (code === PLAY_PAUSE) playpause(cb); if (code === VOLUME_UP) volumeUp(cb); if (code === VOLUME_DOWN) volumeDown(cb); if (code === MUTE) mute(cb); if (code === NEXT) next(cb); if (code === PREV) prev(cb); if (code === STOP) stop(cb); code = 0; LED2.write(false); } // When an IR pulse is detected function onPulseOn(e) { code = (code * 2) | (e.time - lastTime > 0.0008); if (timeout !== undefined) clearTimeout(timeout); timeout = setTimeout(handleCode, 20); lastTime = e.time; } // When IR pulse stops function onPulseOff(e) { lastTime = e.time; } setWatch(onPulseOff, A5, { repeat: true, edge: "rising" }); setWatch(onPulseOn, A5, { repeat: true, edge: "falling" }); setWatch( // Press the button on the pico to enable debug mode and // see the IR code for your own remote function (e) { debug = !debug; console.log(`Debug mode ${debug ? "on" : "off"}`); }, BTN, { repeat: true } );
-
-
Looks like I'd need to register the Pico as a Consumer Device (but not too sure what's involved with that)
Compromise for now is to use a AutoHotkey script to control multimedia functions:
[#NoEnv](https://forum.espruino.com/search/?q=%23NoEnv) ; Recommended for performance and compatibility with future AutoHotkey releases. ; [#Warn](https://forum.espruino.com/search/?q=%23Warn) ; Enable warnings to assist with detecting common errors. SendMode Input ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. ; AutoHotkey Media Keys !M::Send {Media_Play_Pause} ^!Left::Send {Media_Prev} ^!Right::Send {Media_Next} ^!NumpadMult::Send {Volume_Mute} ^!NumpadAdd::Send {Volume_Up} ^!NumpadSub::Send {Volume_Down}
Along with my Pico script:
let kb = require("USBKeyboard"); let debug = 0; let code = 0; let timeout; let lastTime; // function to do something with the code when we get it function handleCode() { timeout = undefined; if (debug) print(code); LED2.write(true); switch(code) { case 16712445: { console.log('Volume +'); kb.setModifiers(kb.MODIFY.CTRL, function() { kb.tap(kb.KEY.F12); }); break; } case 16750695: { console.log('Volume -'); kb.setModifiers(kb.MODIFY.CTRL, function() { kb.tap(kb.KEY.F11); }); break; } case 16754775: { console.log('Play/Pause'); kb.setModifiers(kb.MODIFY.ALT, function() { kb.tap(kb.KEY.M); }); break; } case 16720605: { console.log('Mute'); kb.setModifiers(kb.MODIFY.CTRL, function() { kb.tap(kb.KEY.F10); }); break; } case 16748655: { console.log('Skip'); kb.setModifiers(kb.MODIFY.SHIFT, function() { kb.tap(kb.KEY.N); }); break; } case 16738455: { console.log('Prev desktop'); kb.setModifiers(kb.MODIFY.SHIFT, function() { kb.setModifiers(kb.MODIFY.GUI, function() { kb.tap(kb.KEY.LEFT); }); }); break; } case 16756815: { console.log('Next desktop'); kb.setModifiers(kb.MODIFY.GUI, function() { kb.setModifiers(kb.MODIFY.SHIFT, function() { kb.tap(kb.KEY.RIGHT); }); }); break; } case 16753245: { console.log('Lock'); kb.setModifiers(kb.MODIFY.GUI, function() { kb.tap(kb.KEY.L); }); break; } default: { //console.log('default'); } kb.setModifiers(0, function() {}); } code = 0; LED2.write(false); } function onPulseOn(e) { code = (code*2) | ((e.time - lastTime) > 0.0008); if (timeout!==undefined) clearTimeout(timeout); timeout = setTimeout(handleCode, 20); lastTime = e.time; } function onPulseOff(e) { lastTime = e.time; } setWatch(onPulseOff, A5, { repeat:true, edge:"rising" }); setWatch(onPulseOn, A5, { repeat:true, edge:"falling" }); setWatch(function(e) { debug = !debug; console.log(`Debug mode ${debug ? 'on' : 'off' }`); }, BTN, { repeat: true });
-
Hi all!
I've just been following the docs to try out the USB HID keyboard module, it's great!
I was wondering if this module is able to send mediakey commands (vol up/down, play, pause)My use case is, that I've created a IR Reciever Hat for my Pico which is plugged in to my computer via a USB port that has IR line-of-sight to my remote control, on my desk
I have used the IR communication Espruino examples to determine which button was pressed on my IR remote control, works perfectly!
Now, I want to be able to send volume/media commands to my PC by simply using the remote control.
-
-
Yo @maby - I've tried subtracting the offsets from zero but they're not super consistent, I'm at a bit of a loss trying to figure out how to normalise the values myself.
-
Hi!
I'm working on using Puck 2's accelerometer in order to detect when I'm braking on my bike!
As of yet, I haven't been able to turn off the Accelerometer using
Puck.accelOff()
. Accel reads seem to be blocking my code to turn it off - but I think it's more the case I'm doing something wrong.Here's my code:
// NRF.findDevices(function(devices) { // console.log(devices); // }, 1000); console.log(`Battery ${Puck.getBatteryPercentage()}%`); let accelerometerEnabled = false; // Are we busy? var busy = false; // The device, if we're connected var connectedDevice = false; // The 'tx' characteristic, if connected var txCharacteristic = false; // Function to call 'toggle' on the other Puck function sendDataOverBLE(data) { if (!busy) { busy = true; if (!connectedDevice) { NRF.requestDevice({ filters: [{ id: 'a1:a1:a1:a1:a1:a1 public' }] }).then(function(device) { console.log('got device'); return device.gatt.connect(); }).then(function(device) { console.log('connected'); connectedDevice = device; return device.getPrimaryService("4fafc201-1fb5-459e-8fcc-c5c9c331914b"); }).then(function(service) { return service.getCharacteristic("beb5483e-36e1-4688-b7f5-ea07361b26a8"); }).then(function(characteristic) { txCharacteristic = characteristic; busy = false; }).catch(function(e) { console.log(e); connectedDevice = false; digitalPulse(LED1, 1, 500); // light red if we had a problem busy = false; if (connectedDevicected) { connectedDevice.disconnect(); } }); } else { if (!accelerometerEnabled) { connected.disconnect(); busy = false; return; } txCharacteristic.writeValue(data ? `${data.acc.x}` : "no data yet").then(function() { //digitalPulse(LED2, 1, 500); // light green to show it worked busy = false; }).catch(function(e) { console.log(e); digitalPulse(LED1, 1, 500); // light red if we had a problem busy = false; }); } } else { // console.log('busy'); } } function toggleAccelerometer() { if (accelerometerEnabled) { accelerometerEnabled = false; Puck.accelOff(); digitalWrite(LED1,1); digitalWrite(LED1,0); console.log('Accel OFF'); if (connected) connected.disconnect(); } else { accelerometerEnabled = true; Puck.accelOn(); // default is 12.5Hz, with gyro digitalWrite(LED2,1); digitalWrite(LED2,0); console.log('Accel ON'); } } function checkAccelerometerEnabled(data) { if(accelerometerEnabled) { sendDataOverBLE(data); } } // Call function when the button is pressed setWatch(toggleAccelerometer, BTN, { edge:"rising", debounce:50, repeat: false }); // or Puck.accelOn(1.6); for 1.6Hz low power, without gyro Puck.on('accel', function(data) { if (accelerometerEnabled) { checkAccelerometerEnabled(data); const x = data.acc.x; const y = data.acc.y; const z = data.acc.z; const xZero = 750; const yZero = 15; const zZero = -8200; console.log(x+xZero,y+yZero,z+zZero); } else { // console.log(x+xZero,y+yZero,z+zZero); } });
No issues with sending the data over BLE to my ESP32 however - works like a charm!
One other thing I wanted to know was how to "normalise" the accel's values, but I'll post that up in another convo.
-
I just ripped some of these out of some old Tile keyrings!
Unsuccessfully soldered one so far πit seems there's a coating on top that doesn't like being soldered onto (I used liquid flux, but the connection was still mechanically weak and easily breaks off of the thin coating).
EDIT:
I managed to solder to the + terminal of the Piezo after watching a video that shows you can in fact scratch the coating with a razor blade - it's still a very brittle connection, but I managed to solder to the correct pins to test it out and got beeps!
It was definitely louder, but there's no way i can solder the connections into the watch without something breaking (i already tried twice!)
It was a fail, but I learned some stuff too, so it's ok!
-
Courtesy of Gordon :-)
Bangle.js: Opening and re-assembling
https://www.youtube.com/watch?v=GJHC925yti0
-
You can also use the Set Bangle.js Time button on the About page of the Bangle.js App Loader page
Yes indeed it was π no problem Gordon, thanks for the module!