[{"element_type":"text","content":"\n        \u003ch1\u003eOverview\u003c/h1\u003e\n\u003cp\u003eA media remote receiver for your PC/MAC/thing supporting keyboard media keys.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAlso works with many smart TVs and phones.\u003c/li\u003e\n\u003cli\u003eFlexible CircuitPython-based solution can easily be adapted to other microcontrollers/IR remotes.\u003c/li\u003e\n\u003cli\u003eBuilt-in IR signal decoder utility on serial monitor output.\u003c/li\u003e\n\u003cli\u003eAn easy, inexpensive, solderless build! (if desired)\u003c/li\u003e\n\u003c/ul\u003e\n      ","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/355/original/MediaRemote-Overview.gif?1730779023","metadata":{"caption":""}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/274/original/IRreceiver_small.jpg?1729387696","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n        \u003ch2\u003eBuild \u0026amp; variants\u003c/h2\u003e\n\u003cp\u003eIf this particular build is not for you, check out\u0026nbsp;\u003ca href=\"https://adafruit-playground.com/u/Alain_ManHW/pages/build-patterns-ir-receiver-variants\" target=\"_blank\"\u003ealternative variants in the note here\u003c/a\u003e.\u003c/p\u003e\n      \n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003ePart list\u003c/h3\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5525","metadata":{"name":"RP2040 Pico","url":"https://www.adafruit.com/product/5525","description":"Capable CircuitPython-enabled microcontroller.","quantity":"1","featured":false}},{"element_type":"product","content":"https://www.adafruit.com/product/5422","metadata":{"name":"Breadboard","url":"https://www.adafruit.com/product/5422","description":"Includes helpful labels to identify pin locations","quantity":"1","featured":false}},{"element_type":"product","content":"https://www.adafruit.com/product/157","metadata":{"name":"IR remote signal receiver","url":"https://www.adafruit.com/product/157","description":"Works with many IR remotes that control TVs/DVDs/AV receivers, etc.","quantity":"1","featured":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eProgram your device\u003c/h1\u003e\n\u003ch3\u003eInstalling CircuitPython environment\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eDownload .uf2 file here:\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://circuitpython.org/board/raspberry_pi_pico/\" target=\"_blank\"\u003ehttps://circuitpython.org/board/raspberry_pi_pico/\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003ePlug in USB cable from PC to RP2040 board while holding the\u0026nbsp;\u003cstrong\u003eBOOTSEL\u003c/strong\u003e button.\n\u003cul\u003e\n\u003cli\u003eA new drive should get mounted on your system.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eDrag/drop downloaded .uf2 file onto newly mounted drive (\u003cstrong\u003eRPI-RP2\u003c/strong\u003e).\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3\u003eInstalling libraries and project code\u003c/h3\u003e\n\u003cp\u003eFrom \"CircuitPython Library Bundle\" (\u003ca href=\"https://circuitpython.org/libraries\" target=\"_blank\"\u003edownload here\u003c/a\u003e):\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eCopy from bundle .zip file to the microcontroller \u003cstrong\u003e[drive:]\\lib\\\u003c/strong\u003e folder:\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eadafruit_hid\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eFrom the \u003cstrong\u003ePCMediaRemote\u003c/strong\u003e release page (\u003ca href=\"https://github.com/alainman-krh/Projects_Circuits/releases/tag/PCMediaRemote-v0.1\" target=\"_blank\"\u003edownload here\u003c/a\u003e):\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eDownload and unzip the \"Source code (zip)\" file from the \"Assets\" section.\u003c/li\u003e\n\u003cli\u003eCopy the \"unzipped\" custom project code to microcontroller\u0026nbsp;\u003cstrong\u003e[drive:]\u003c/strong\u003e:\n\u003cul\u003e\n\u003cli\u003e[PCMediaRemote folder]\u003cstrong\u003e\\lib_cktpy\\*\u003c/strong\u003e =\u0026gt; [drive:]\u003cstrong\u003e\\lib\\\u003c/strong\u003e\n\u003c/li\u003e\n\u003cli\u003e[PCMediaRemote folder]\u003cstrong\u003e\\pkg_install\\MediaRemote_RP2040\\*.py\u003c/strong\u003e =\u0026gt; [drive:]\u003cstrong\u003e\\\u003c/strong\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eNOTE: Feel free to check for newer versions of\u0026nbsp;\u003cstrong\u003ePCMediaRemote\u003c/strong\u003e on the releases page. Code from the \u003cstrong\u003emain\u003c/strong\u003e branch might also be functional, but explicit releases are less likely to have issues.\u003c/p\u003e\n\u003ch3\u003eCustomizing your solution\u003c/h3\u003e\n\u003cp\u003eYou can directly modify the \u003cstrong\u003emain.py\u003c/strong\u003e file on the \u003cstrong\u003e[drive:]\\\u003c/strong\u003e folder. Every time you save the file, CircuitPython will restart with the updates applied.\u003c/p\u003e\n\u003cp\u003eNote that if the file gets corrupted for some reason, your changes will be lost. It is recommended to work from a folder on your PC, and manually upload (ex: drag/drop) the changes to the CircuitPython drive.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eCode breakdown\u003c/h1\u003e\n\u003ch3\u003eReactive programming\u003c/h3\u003e\n\u003cp\u003eThis project implements/uses event handlers (\u003ca href=\"https://en.wikipedia.org/wiki/Reactive_programming\" target=\"_blank\"\u003e\"reactive programming\"\u003c/a\u003e) to simplify the code and help with readability.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eWith reactive programming, a solution does not have to explicitly tell the microcontroller to scan for IR messages, then figure out somehow if a button was pressed, released, etc.\u003c/li\u003e\n\u003cli\u003eInstead, the program uses a more \"declarative\" approach where it merely has to describe what to do \u003cem\u003ewhen \u003c/em\u003ea button press (or button release) is detected.\u003c/li\u003e\n\u003cli\u003eBecause of this different approach, the code might look a bit unusual compared to other project examples.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThat said, the example should be relatively easy to modify for your particular needs.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"alert","content":"\u003cp\u003eAdvantages of reactive programming are not that obvious on such a small project, but applying this methodology can help with more complex cases.\u003c/p\u003e","metadata":{"class":"element alert-element build-alert alert-info","markdown":"Advantages of reactive programming are not that obvious on such a small project, but applying this methodology can help with more complex cases.","alert_type":"info"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003eUnderstanding \u003cstrong\u003emain.py\u003c/strong\u003e (\u003ca href=\"https://github.com/alainman-krh/Projects_Circuits/blob/main/PCMediaRemote/pkg_install/MediaRemote_RP2040/main.py\" target=\"_blank\"\u003elink\u003c/a\u003e)\u003c/h3\u003e\n\u003cp\u003eThe code is composed of 3 main objects/data structures:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003ccode\u003eSIGNAL_MAP\u003c/code\u003e: Creates a mapping between decoded IR signals and which \"function\" (play/pause/...) they represent.\u003c/li\u003e\n\u003cli\u003e\n\u003ccode\u003eKEYMAP\u003c/code\u003e: Creates a mapping between button \"functions\" (play/pause/...), and what key to send to the PC.\u003c/li\u003e\n\u003cli\u003e\n\u003ccode\u003eIRDetect\u003c/code\u003e: A declarative way to describe how to react to button press/release events.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eNote that in the example, \u003ccode\u003eSIGNAL_MAP\u003c/code\u003e is constructed from the combination of \u003ccode\u003eSIGNAL_MAP_ADAFRUIT_389_CCC/_EXTRAS\u003c/code\u003e, and \u003ccode\u003eSIGNAL_MAP_LG_CCC/EXTRAS\u003c/code\u003e. The code calls \u003ccode\u003eSIGNAL_MAP.update(...)\u003c/code\u003e to add new (or update existing) key:value mappings of the \u003ccode\u003eSIGNAL_MAP\u003c/code\u003e python \u003ccode\u003edict\u003c/code\u003e for both remotes.\u003c/p\u003e\n\u003cp\u003eTo support a different IR remote, the \u003ccode\u003eSIGNAL_MAP\u003c/code\u003e object should add in its specific IR code mappings. Follow the pattern used by\u0026nbsp;\u003ccode\u003eSIGNAL_MAP_LG_CCC\u003c/code\u003e to add your own custom \"\u003ccode\u003eSIGNAL_MAP_X\u003c/code\u003e\". Also feel free to remove predefined \u003ccode\u003eSIGNAL_MAP_*\u003c/code\u003e values to minimize accidental detection of these other remotes.\u003c/p\u003e\n\u003cp\u003eBy default, \u003cstrong\u003ePCMediaRemote\u003c/strong\u003e uses \u003ccode\u003eirdetect\u003c/code\u003e to decode NEC control codes:\u003c/p\u003e\n\u003cp style=\"padding-left: 40px;\"\u003e\u003ccode\u003eirdetect = IRDetect(rx, PDE.DecoderNEC(), PDE.DecoderNECRPT(), msgRPT=PDE.IRMSG32_NECRPT)\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eTo detect Samsung codes instead, substitute \u003ccode\u003ePDE.DecoderNEC()\u003c/code\u003e =\u0026gt; \u003ccode\u003ePDE.DecoderSamsung()\u003c/code\u003e.\u003c/p\u003e\n\u003ch3\u003eCapturing IR control codes of other remotes\u003c/h3\u003e\n\u003cp\u003eTo make supporting other remotes a bit easier,\u0026nbsp;\u003cstrong\u003ePCMediaRemote\u003c/strong\u003e includes a built-in feature that prints out any NEC code it detects to the serial output.\u0026nbsp; Some information on how to access the serial output is provided in the learn guide \"\u003ca href=\"https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console\" target=\"_blank\"\u003eConnecting to the serial console\u003c/a\u003e\". The following shows the type of output you can expect from the console:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"MediaRemote: ready to receive!\nNew message: NEC 0x20DF40BF (VOL+)\nRepeat!\nNew message: NEC 0x20DFC03F (VOL-)\nRepeat!\nUnknown message: NEC 0x20DF8E71","metadata":{"language":"terminal","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eIn the serial output above, the first 2 messages are known and originate from VOL+/- buttons.\u003c/p\u003e\n\u003cp\u003eWhen a message is not mapped to anything (despite being recognized/decoded): it will also get printed to console, as shown for the third and final message.\u0026nbsp;Simply write down this code, and add it to your\u0026nbsp;\u003ccode\u003eSIGNAL_MAP\u003c/code\u003e dictionary.\u003c/p\u003e\n\u003cp\u003eNote that Python requires the \"\u003ccode\u003e0x\u003c/code\u003e\" prefix to recognize the code as a hexadecimal (hex) number.\u003c/p\u003e\n\u003ch1\u003eAbout the IR library\u003c/h1\u003e\n\u003cp\u003eThe code uses a custom module to perform \u003cstrong\u003eC\u003c/strong\u003eonsumer \u003cstrong\u003eel\u003c/strong\u003eectronics \u003cstrong\u003eIR\u003c/strong\u003e \u003cstrong\u003ecom\u003c/strong\u003emunications (\u003cstrong\u003eCelIRcom\u003c/strong\u003e - to encode/decode IR signals). In turn, \u003cstrong\u003eCelIRcom\u003c/strong\u003e heavily leverages the \u003cstrong\u003epulseio\u003c/strong\u003e module - a \"core module\" of CircuitPython.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eCurrently only supports NEC (/Samsung) protocol, with some support for a Sony protocol.\u003c/li\u003e\n\u003cli\u003ePreferable to chose an IR remote (universal remote?) that \"speaks\" NEC.\u003c/li\u003e\n\u003c/ul\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n        \u003ch1\u003eAdditional resources\u003c/h1\u003e\n\u003ch2\u003eHardware suggestions\u003c/h2\u003e\n\u003cp\u003eBring Your Own Remote!\u003c/p\u003e\n      \n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/275/original/IRremotes_small.jpg?1729651066","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eIf your particular remote doesn't seem to be working, the following should work \"out-of-the-box\" with the provided code:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAdafruit mini remote control (\u003ca href=\"https://www.adafruit.com/product/389\" target=\"_blank\"\u003ehere\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eLG-compatible remote (\u003ca href=\"https://www.amazon.ca/dp/B0BHT5BW41\" target=\"_blank\"\u003ehere\u003c/a\u003e - has a responsive feel).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ePlease ensure the remote you select is capable of sending out NEC/Samsung codes. Otherwise, the IR-library used for this project will not be able to decode the signals. A good way to check is to look at the serial output from the \u003cstrong\u003ePCMediaRemote\u003c/strong\u003e project. If it prints out detected signals, that means the signals are being decoded.\u003c/p\u003e\n\u003cp\u003eUniversal remotes that come bundled with satellite receivers are also good, widely available options. For example, the \"TV\" device of an Arris IRC600 remote should also \"just work\" with the\u0026nbsp;\u003cstrong\u003ePCMediaRemote\u003c/strong\u003e default configuration (if programmed to LG code \"11423\").\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"alert","content":"\u003cp\u003eIn an attempt to simplify operation, some remotes will redirect certain button presses to devices other than the currently active one (to the frustration of particular users wanting 1 remote to control everything). For example: The Arris IRC600 will redirect CH+/- \u0026amp; CH0-9 to the satellite receiver despite the \"TV\" mode being active. To bypass this feature, follow the instructions in the \"PROGRAMMING CHANNEL CONTROL LOCK\" section of the manual.\u003c/p\u003e","metadata":{"class":"element alert-element build-alert alert-info","markdown":"In an attempt to simplify operation, some remotes will redirect certain button presses to devices other than the currently active one (to the frustration of particular users wanting 1 remote to control everything). For example: The Arris IRC600 will redirect CH+/- \u0026 CH0-9 to the satellite receiver despite the \"TV\" mode being active. To bypass this feature, follow the instructions in the \"PROGRAMMING CHANNEL CONTROL LOCK\" section of the manual.","alert_type":"info"}},{"element_type":"alert","content":"\u003cp\u003eThe IRC600 \"control lock\" instructions tell you to hold the \"SAT\" button to lock/unlock channel control. However, my remote required the \"TV\" button to be held to perform this operation.\u003c/p\u003e","metadata":{"class":"element alert-element build-alert alert-warning","markdown":"The IRC600 \"control lock\" instructions tell you to hold the \"SAT\" button to lock/unlock channel control. However, my remote required the \"TV\" button to be held to perform this operation.","alert_type":"warning"}},{"element_type":"text","content":"\n  \n  \n  \n        \u003ch2\u003eRelated Notes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://adafruit-playground.com/u/Alain_ManHW/pages/build-patterns-ir-receiver-variants\" target=\"_blank\"\u003eBuild patterns: IR receiver variants\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eLearn guides\u003c/h2\u003e\n      \n\n\n","metadata":{}},{"element_type":"guide","content":"https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython","metadata":{"guide_id":"1845","page_id":"11003"}},{"element_type":"guide","content":"https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console","metadata":{"guide_id":"1845","page_id":"11030"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003eOther documentation\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.circuitpython.org/projects/hid/en/latest/index.html\" target=\"_blank\"\u003eAdafruit HID library (USB Human Interface Devices)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.circuitpython.org/en/latest/shared-bindings/pulseio/\" target=\"_blank\"\u003eCircuitPython pulseio module\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}}]