tag:blogger.com,1999:blog-57435204474058667262024-03-16T02:09:21.622+01:00Jacek Fedoryński's blogJacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.comBlogger56125tag:blogger.com,1999:blog-5743520447405866726.post-81683556941645396752022-07-27T15:45:00.001+02:002022-07-27T15:46:07.569+02:00DIY Surface Dial<p>Microsoft's Surface line of hardware has some nice computers and accessories. Among the accessories there's the <a href="https://www.microsoft.com/en-us/d/surface-dial/925r551sktgn">Surface Dial</a> - a Bluetooth knob that can do things like volume control, scrolling, undo/redo and some other functions in certain applications, mostly artist-oriented. For some reason the physical form of the Surface Dial appeals to me, but since its price is not exactly in the impulse buy territory and I don't have a practical need for it, I never got one. But now I have made <a href="https://github.com/jfedor2/radial-controller">my own version</a> of it. It's not as nice as the real one and it's missing some of the functionality, but it really does work as a Surface Dial in the software that supports it.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAa73CAanTTSTIhaJ4C85aEVrsQcgmSEt5L3zmyWakN0pYSP8R6ClZWWL-EtTJxf8UJofuRcAZ4B6Ut3h9A50M62lP1QGtXJN3RTY3enCyBByyuGij-fiPOK9AgwaugUKqazNRYXNhF2jwkd8JbvWpA-K3X_3tTLBAXak9b5o2GUcr9qY8uJzlB2GBjTzrn11lfqI/s2773/radial-controller.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="2080" data-original-width="2773" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAa73CAanTTSTIhaJ4C85aEVrsQcgmSEt5L3zmyWakN0pYSP8R6ClZWWL-EtTJxf8UJofuRcAZ4B6Ut3h9A50M62lP1QGtXJN3RTY3enCyBByyuGij-fiPOK9AgwaugUKqazNRYXNhF2jwkd8JbvWpA-K3X_3tTLBAXak9b5o2GUcr9qY8uJzlB2GBjTzrn11lfqI/s400/radial-controller.jpg"/></a></div>
<p>There are two aspects to this device, making the physical hardware and programming it so that Windows recognizes it as a Surface Dial.</p>
<p>From the hardware perspective, we need two things - a way of detecting the dial's rotation and a button. On the real Surface Dial the entire knob works as a button, but in my version, there's a separate button in the middle, made using a mechanical keyboard switch. As for the dial itself, instead of using an off-the-shelf rotary encoder, I made my own using small neodymium magnets and two Hall effect sensors. Its principle of operation is the same as with other <a href="https://en.wikipedia.org/wiki/Incremental_encoder">incremental encoders</a>, the sensors are oriented so that their signals have a phase difference. In theory we could get better resolution by using the full resolution of the sensors' output, instead of treating them as binary, but I haven't done that. The resolution I got is determined by the number of magnets (48).</p>
<p>I designed the case for the device in Fusion 360 and 3D printed it. The dial sits on a 6806 ZZ bearing and has a very satisfying feel. Here's what it looked like during assembly.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPU0gLvD4ZuD0jOEZ_K8LE7Y3tZhMUIN9zKDD-jFF3eVZMwCV_oZGQvuHRWc9hk6FCO7Y-wCazC-YI2ux3-Tui7z89rcPTscvZtaJxkfMAWtKitXbPAIDq7F6EKmv7Mflhv9STdF0J4RpL9juDObEFLmR46BBakjyrDEWjCegiUL0kU12pNW4i6TFtv_whtKCFSLI/s4032/radial-controller-internals.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPU0gLvD4ZuD0jOEZ_K8LE7Y3tZhMUIN9zKDD-jFF3eVZMwCV_oZGQvuHRWc9hk6FCO7Y-wCazC-YI2ux3-Tui7z89rcPTscvZtaJxkfMAWtKitXbPAIDq7F6EKmv7Mflhv9STdF0J4RpL9juDObEFLmR46BBakjyrDEWjCegiUL0kU12pNW4i6TFtv_whtKCFSLI/s400/radial-controller-internals.jpg"/></a></div>
<p>For the microcontroller I chose the <a href="https://www.adafruit.com/product/4900">Adafruit QT Py RP2040</a>, it's small and uses the RP2040 chip from Raspberry Pi (it has a similar form factor to Seeed Studio's <a href="https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html">XIAO RP2040</a>).</p>
<p>Since we're talking about Microsoft, I half-expected the Surface Dial's protocol to be some proprietary nonsense that would require reverse engineering to replicate. Imagine my surprise when I found out that it's actually standard HID and there's proper <a href="https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/radial-controller-protocol-implementation">documentation</a> for it. All you have to do is put the right stuff in the HID report descriptor and it works similarly to a regular USB mouse or keyboard.</p>
<p>I put all the code and 3D-printable files <a href="https://github.com/jfedor2/radial-controller">on GitHub</a>, along with a list of components used and instructions how to put them together.</p>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com1tag:blogger.com,1999:blog-5743520447405866726.post-80497613473073398292022-07-09T19:59:00.000+02:002022-07-09T19:59:07.896+02:00Two mice, two cursors<p>I always thought that when you connect two mice to a computer, there should be two mouse cursors, one for each mouse. Unfortunately that's not really how it works on modern operating systems, at least not by default. Software add-ons exist that draw a second cursor for the second mouse (and also perform some tricks to make button clicks work as expected). I'm sure they work fine, but I came up with a pure hardware solution to the problem that requires no special software running on the host. Here's a video demonstrating this solution.</p>
<div class="separator" style="clear: both; text-align: center;"><iframe width="480" height="270" src="https://www.youtube.com/embed/XYER6yjNt-I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
<p>What you can see here is two mice, connected through a USB hub to an Arduino Leonardo with a USB Host Shield. The mice are wireless, but they use 2.4 GHz USB receivers so they're effectively USB devices. The Arduino is connected to the computer and acts as a USB mouse.</p>
<p>The Arduino reads inputs from the two mice, does its magic, and sends the resulting inputs to the computer. What's the trick that makes the computer display two cursors? If you look closely, you'll notice that the two cursors flicker a bit. That's because they're not really two cursors, instead it's just the one normal cursor oscillating quickly between two positions on the screen, appearing as two due to persistence of vision. The Arduino keeps track of the X/Y positions of both cursors and updates them based on the inputs received from each mouse. Then it alternates between the two causing the illusion of two cursors. To be able to do that it uses absolute cursor positioning, unlike a regular mouse, which only sends the X/Y deltas and doesn't know where on the screen the cursor is at any moment. (I have previously used absolute cursor positioning for both <a href="https://blog.jfedor.org/2020/09/hat-mouse.html">good</a> and <a href="https://blog.jfedor.org/2020/09/usb-rubber-ducky-with-mouse-input.html">evil</a>.)</p>
<p>One remaining problem is what to do when you click a button on one of the mice. The user will naturally expect for the click to happen at the screen position of the cursor corresponding to that mouse. So we can't keep alternating between the two cursors. For as long as the button is pressed, we only send the cursor position of the mouse that's doing the clicking. This means that the second cursor disappears for a brief moment, but the clicks work as expected.</p>
<p>If you want to play around with it, I posted the source code <a href="https://github.com/jfedor2/mouse-multiplexer">on GitHub</a>. It uses the standard USB HID protocol and works with Windows, Linux and Mac, without any additional software needed on the computer.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwLidaFo3X3j8QEBpJ5J8DYgAV_-E1oI-TawP3AkopCqeE05SOx15nsqtn2wBIsEo9_N6IRDNcIS74QJ12tmyeozTIGIJgQ5hFbwlkKG6nD4QRJypbts7e8A9fDSeV2czWxxPuvU5NZP_NIyx6P2plBXZcj2EUyRUe2iTziWyXJOoiYSVg4dgMrpXu2i1x7f5_9UA/s4032/PXL_20210930_175322853.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwLidaFo3X3j8QEBpJ5J8DYgAV_-E1oI-TawP3AkopCqeE05SOx15nsqtn2wBIsEo9_N6IRDNcIS74QJ12tmyeozTIGIJgQ5hFbwlkKG6nD4QRJypbts7e8A9fDSeV2czWxxPuvU5NZP_NIyx6P2plBXZcj2EUyRUe2iTziWyXJOoiYSVg4dgMrpXu2i1x7f5_9UA/s400/PXL_20210930_175322853.jpg"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com1tag:blogger.com,1999:blog-5743520447405866726.post-16886474623140108812022-07-07T21:20:00.003+02:002022-07-07T21:21:36.287+02:00Razer Raion padhack<p>One of the problems when making a custom fightstick (arcade controller for fighting games) is modern console compatibility. While it was easy to make an Arduino or similar board work as a USB controller for the PS3, unfortunately it is no longer the case with the PS4 and PS5. Only licensed controllers work with them due to restrictions introduced by Sony. Every licensed controller has a private key embedded in it that allows it to perform some kind of authentication when connected to a console. One solution to this problem is a practice known as padhacking: taking the insides of an existing licensed controller and transplanting them into a different enclosure, for example a fightstick-shaped one, carefully soldering wires between buttons and the right places on the donor PCB.</p>
<p>In theory you can use any controller for this, like a DualShock 4 or a DualSense, but it makes sense to choose one that will be relatively cheap to obtain and also easy to solder to. One such controller is the Razer Raion. It was originally released for the PS4, but since it qualifies as a <a href="https://blog.playstation.com/2020/08/03/playstation-5-answering-your-questions-on-compatible-ps4-peripherals-accessories/">"specialty peripheral"</a>, it also works in PS5 games. I got one and made a mixbox-layout fightstick using its PCB.</p>
<p>First I had to figure out where the solder points that I need are on the PCB. Fortunately I found this <a href="https://twitter.com/ShadalooFrieza/status/1398707787446751235">helpful tweet</a> and with this information it was a fairly straightforward job.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidec7_6-riZ3YaG2ORDbV29nhDnfUksnmxEWisPz7SAVKvGrxbdeTHOdfx3ciUZYBLIordtFAcnLXMIVZKw6hl5Gz4QiyqYxldI6IPdYKRbRchlID3eoVBa9L5nhf-dBlf7oBMm6zc7eiIuymo_8iF1gwYdAkdU4Jw5UtLIv490wPzvajQb_lQjFp5obcgTFjVxls/s4032/PXL_20220209_225828931.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidec7_6-riZ3YaG2ORDbV29nhDnfUksnmxEWisPz7SAVKvGrxbdeTHOdfx3ciUZYBLIordtFAcnLXMIVZKw6hl5Gz4QiyqYxldI6IPdYKRbRchlID3eoVBa9L5nhf-dBlf7oBMm6zc7eiIuymo_8iF1gwYdAkdU4Jw5UtLIv490wPzvajQb_lQjFp5obcgTFjVxls/s400/PXL_20220209_225828931.jpg"/></a></div>
<p>The rest of the fightstick was similar to what I've done <a href="https://blog.jfedor.org/2022/07/fightsticks.html">previously</a>, in fact I just modified one of the designs to accomodate the Raion PCB. Here's what it looks like inside. As you can see it uses common ground.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIjEp2AtzIhJcxb4uU1WvvSuxZN2ZShqMo-feyLUVAWTVwLOGCduz4o98I_cg-M54cig1WOVG6vjfmk2t1sFre5XSB_xHMlKhejsUhRMjPpkFQ3m55VxR2U9NVbyL01Uo-VYB0JHtlm9HW-PgX12kxXXLI2MI04kpBZfN32Rzmttzx9twa0GPBJOLOG6DIZcARBJs/s3719/PXL_20220210_004235960.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="3719" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIjEp2AtzIhJcxb4uU1WvvSuxZN2ZShqMo-feyLUVAWTVwLOGCduz4o98I_cg-M54cig1WOVG6vjfmk2t1sFre5XSB_xHMlKhejsUhRMjPpkFQ3m55VxR2U9NVbyL01Uo-VYB0JHtlm9HW-PgX12kxXXLI2MI04kpBZfN32Rzmttzx9twa0GPBJOLOG6DIZcARBJs/s400/PXL_20220210_004235960.jpg"/></a></div>
<p>One thing to keep in mind when converting a controller like this is the matter of SOCD cleaning - what happens when you press opposing direction buttons at the same time? Most traditional controllers don't have to worry about this because it's physically impossible to simultanously trigger opposing directions on them. But when you make a stick that has separate buttons for up, down, left and right, that can be pressed independently, it's something you have to start thinking about. In case of the Razer Raion, it uses a scheme called <em>first input priority</em>, meaning that if you press and hold left, then press and hold right, it will keep sending left. When you release left, then it will start sending right. If I didn't like this, I'd have to add an external SOCD cleaner between the buttons and the Raion PCB.</p>
<p>I posted the 3D-printable models for this stick <a href="https://www.printables.com/model/131827-slimbox-mrr-razer-raion-padhack">on Printables</a>. It uses Kailh low profile (choc v1) mechanical keyboard switches for the buttons. Here's what the final result looks like.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo59D4yOM9FYA4G0Mc9DHP-Tb4VuDU-CYiebuA5GA3pCm54cPReudTJDw2HtSrvXlBD4plW8nGm4zgKwf8i7JF22Nywl-u9z5dE5-6E4S-hYGysHtglYNe_zYNKTtPcFmkc9WLMxRhfYnsjYvY2v5uMEPFfGDLS0eKDxRMZvnbK2KVgkGUR62QGd9e6admAaoi524/s4032/PXL_20220210_015003895.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo59D4yOM9FYA4G0Mc9DHP-Tb4VuDU-CYiebuA5GA3pCm54cPReudTJDw2HtSrvXlBD4plW8nGm4zgKwf8i7JF22Nywl-u9z5dE5-6E4S-hYGysHtglYNe_zYNKTtPcFmkc9WLMxRhfYnsjYvY2v5uMEPFfGDLS0eKDxRMZvnbK2KVgkGUR62QGd9e6admAaoi524/s400/PXL_20220210_015003895.jpg"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-68321204857596986262022-07-06T19:38:00.002+02:002022-07-27T15:45:56.986+02:00Flatbox<p>Having previously made some <a href="https://blog.jfedor.org/2022/07/fightsticks.html">3D printed fightsticks</a> (arcade controllers for fighting games) that were just plastic boxes with holes for arcade buttons or mechanical keyboard switches, I started thinking, could I make one that's even thinner? On my previous designs I just soldered wires to the keyboard switches, but they're really intended to be soldered onto a printed circuit board. Using a PCB instead of the wire spaghetti inside the case seemed like a good way to shave a few millimeters off. And it turns out there are companies in China that will manufacture a custom PCB for you for very reasonable prices. And thus the <a href="https://github.com/jfedor2/flatbox">Flatbox</a> was born. I ended up making four revisions of it.</p>
<p>Up to this point I was using Arduino Pro Micros as the brains of my fightsticks, so it seemed natural to start with a PCB that I could solder a Pro Micro onto. The PCB would just serve as a connection between the Arduino's pins and the keyboard switches (I used Kailh choc v1 low profile switches). I designed my board in KiCAD, arranged the switch footprints in a hitbox-style layout, generated the Gerber files and sent them off to JLCPCB for manufacturing. After some days I was excited to receive a package with my boards inside.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTpI_AAP57_jyvdv0R1psEFWCBFdOS3UtBMdmNeAO_amsxOHQ8wf1voA4JMKYQj6Zm-fjL9OGIzHDtIbc1wlhg6m60N4g60InV0XiTXBQRF-jWfvJRI2M98KmpBoheTBBguKA6lwFQQ837tRZ9QI4QcFNGLjn-gRjHOwwTY_mDMNBr4q-ScwhOo8VwvOH6-MeSBQc/s4032/PXL_20210617_102610168.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTpI_AAP57_jyvdv0R1psEFWCBFdOS3UtBMdmNeAO_amsxOHQ8wf1voA4JMKYQj6Zm-fjL9OGIzHDtIbc1wlhg6m60N4g60InV0XiTXBQRF-jWfvJRI2M98KmpBoheTBBguKA6lwFQQ837tRZ9QI4QcFNGLjn-gRjHOwwTY_mDMNBr4q-ScwhOo8VwvOH6-MeSBQc/s400/PXL_20210617_102610168.jpg"/></a></div>
<p>I've never done anything like this before so I wasn't sure if the boards would even work at all. I'm used to prototyping on breadboards, if you make a wrong connection there it's usually not a big deal and it's a matter of seconds to correct it. Here if I made a mistake, not only would it cost money, but I'd also have to wait a week or two for another package from China. But fortunately everything worked great! I quickly designed and 3D printed an enclosure for it. I was very pleased with the result, just 10 millimeters thick!</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWX38UBj6qVMJQPFDv6sXElYOCD0XxnXvnvJyWjG3EV8YS4TgLVIw7AQgFUy3mF9kupRBonturr6MeAiTROtzzSx5YcFPRXvWUQRV7pYvrxLYPZ1XCupoUZJgEpqhRBdtnzcdMNE8oxVYcW6NcFUiFWZ2jABhfpuriQVKJdznzDc12JGcx4LIxhEzpixoT1bOwdDU/s4032/PXL_20210816_132810566.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWX38UBj6qVMJQPFDv6sXElYOCD0XxnXvnvJyWjG3EV8YS4TgLVIw7AQgFUy3mF9kupRBonturr6MeAiTROtzzSx5YcFPRXvWUQRV7pYvrxLYPZ1XCupoUZJgEpqhRBdtnzcdMNE8oxVYcW6NcFUiFWZ2jABhfpuriQVKJdznzDc12JGcx4LIxhEzpixoT1bOwdDU/s400/PXL_20210816_132810566.jpg"/></a></div>
<p>I was encouraged by this initial success, but I thought having to solder an Arduino board onto my PCB wasn't very elegant. Surely an Arduino is just another PCB and I should be able to include the microcontroller and all the other necessary components on my PCB and eliminate the need for an additional board. That's what I did for revision 2. I designed the board to use SMD (surface mount) components for everything except the keyboard switches and option buttons. I would probably not be able to solder them manually, but fortunately JLCPCB will happily do the assembly for you, you just have to provide two more files in addition to the Gerbers (list of components and their placement on the board). This time I was even more afraid that it wouldn't work at all, because there was a lot more I could mess up, but surprisingly the whole thing worked on the first attempt. Because it uses the same chip as the Pro Micro (ATmega32U4), I was able to use the same firmware. I was very happy, because even though manufacturing the boards was a little more expensive, it was suddenly starting to look somewhat like a real product.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYDo1aZYrmSkrkAVZ4ogkjYz2QgQ2FZTyZ7NzHiZUdXprsTC6H32ejd0HrSw12WaZ_fQ76aBwqf99GIBQR05bWECAObLg-e5bN69F92qjkSfoCV7i9Ezy2vBSDxH_i0RlZ6LztAn0ou4p6giOwykhnGigrbwGTBiQeZ7er3wJMwrF9U5JH3LOY6kpdUzaOqT6t-f0/s4032/PXL_20210729_114653439.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYDo1aZYrmSkrkAVZ4ogkjYz2QgQ2FZTyZ7NzHiZUdXprsTC6H32ejd0HrSw12WaZ_fQ76aBwqf99GIBQR05bWECAObLg-e5bN69F92qjkSfoCV7i9Ezy2vBSDxH_i0RlZ6LztAn0ou4p6giOwykhnGigrbwGTBiQeZ7er3wJMwrF9U5JH3LOY6kpdUzaOqT6t-f0/s400/PXL_20210729_114653439.jpg"/></a></div>
<p>Speaking of firmware, while it's easy to make a USB HID device that works with a PC or a PS3, it is unfortunately not the case with more modern consoles. From the PS4 onwards, Sony started restricting their systems to only work with licensed controllers. Each licensed pad or stick has some special chip with a private key inside it that lets it authenticate to the console. And DIY-ers are out of luck. Except you can buy PCBs that somehow get around Sony's restrictions (I don't know how they do it). I wanted a version of the Flatbox that was compatible with the PS4 so for revision 3 I went back to the idea of soldering an add-on board onto the main PCB. I chose the Brook PS3/PS4 board because of its small size. The only SMD components on the main board are the USB port and the two resistors that it requires.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMnG2qfqiOmRvOQ_VPLG7bjB2G1cVXLx0IYyhJ7_1UZtrGAPWdHgRIhsTKBVZnY80uo59uj-NQnIG9RxRZuxLIDq-4ML-_BnmvlM88oiBQMuWnj4GdCbq6UySMHJyq1AYJOAA9V4l5wlbtpyRskQrBF-U4jxWY4h_Niu4YzNfqVRkoD2YsgyI8GqjuWY7j2KhOaBc/s4032/PXL_20210901_132019539.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMnG2qfqiOmRvOQ_VPLG7bjB2G1cVXLx0IYyhJ7_1UZtrGAPWdHgRIhsTKBVZnY80uo59uj-NQnIG9RxRZuxLIDq-4ML-_BnmvlM88oiBQMuWnj4GdCbq6UySMHJyq1AYJOAA9V4l5wlbtpyRskQrBF-U4jxWY4h_Niu4YzNfqVRkoD2YsgyI8GqjuWY7j2KhOaBc/s400/PXL_20210901_132019539.jpg"/></a></div>
<p>The fourth and final revision of the Flatbox again has all the components on the main PCB and doesn't require an add-on board. It is similar to revision 2, but instead of the ATmega32U4 chip it uses Raspberry Pi's RP2040. It is the revision I like best, even though it's not compatible with the PS4 or the PS5.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbSK9x0QMgK5h7Zrse7q-mxzJh_WKWjdrtr2Er14W5U_96Fdj7BVQuO4LnJij7Ab8AgkWP3H1KKNTp2DeH9HyRwWJSaUQtZsi2zJyQkBtuYbOISmBRVqbk3SYiYPGb65ePW9JA2qS2xMrEI--1bNJElTFsbnDdeczUUnmWi7_yzdXt-0tc7bhJmHCoay3KCLbeX_U/s4032/PXL_20210914_145539456.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbSK9x0QMgK5h7Zrse7q-mxzJh_WKWjdrtr2Er14W5U_96Fdj7BVQuO4LnJij7Ab8AgkWP3H1KKNTp2DeH9HyRwWJSaUQtZsi2zJyQkBtuYbOISmBRVqbk3SYiYPGb65ePW9JA2qS2xMrEI--1bNJElTFsbnDdeczUUnmWi7_yzdXt-0tc7bhJmHCoay3KCLbeX_U/s400/PXL_20210914_145539456.jpg"/></a></div>
<p>All the files needed to make your own Flatbox are <a href="https://github.com/jfedor2/flatbox">on GitHub</a>, including KiCAD projects for the PCBs, 3D-printable models for the case and source code for the firmware.</p>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com3tag:blogger.com,1999:blog-5743520447405866726.post-40047045101567785072022-07-04T23:00:00.001+02:002022-07-04T23:04:15.521+02:00Fightsticks<p>
Fighting games like Virtua Fighter, Tekken or Street Fighter originated at the arcades and have traditionally been played on cabinets with heavy duty joysticks and buttons. Even though they're mostly played on consoles and PCs these days, many players use arcade sticks modeled after the arcade cabinets, either because they consider them superior to controllers or simply because they enjoy their old school look and feel.
</p>
<p>
Arcade stick parts like buttons and joysticks can be bought separately so it's fairly easy to make your own stick. All that's needed is some kind of a box and a microcontroller that will read the state of the buttons and send the appropriate inputs to the PC or console. Not suprisingly, there's a thriving DIY community of fightstick makers.
</p>
<p>
I designed a few arcade stick cases meant to be 3D printed. The ones shown below all use an Arduino Pro Micro as the brains, running <a href="https://github.com/jfedor2/gamepad">this firmware</a>, compatible with PC and PlayStation 3. If you like any of them and want to try making your own, I've posted all the 3D-printable models <a href="https://www.printables.com/social/7792-jfedor/models">on Printables</a>, along with more pictures and details on how to make them.
</p>
<p>
The <a href="https://www.printables.com/model/133135-arcade-stick-with-sanwa-parts">first one</a> uses the most classic layout, with a Sanwa JLF joystick, 30 mm action buttons and 24 mm option buttons at the back. I made versions with 6 and 8 actions buttons.
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhMqw7zsyQSZjfYprdoEghzWYfgk27yEnZyNMV90HfD70ehdfe2nCIa05LV54pzt1UnIaXy8N97vH9f5oACyKZGz-sFABNuPUblrh173DrGZcf5RGfqFxGdQF4eFCRUx9Fqw_jysZO2JU3rVL7lkpMWqMgXeik7B8tuWqkW7n6LXPlBpJPC3Oie2hbdt9YcejPK7s/s4032/PXL_20210623_110342320.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhMqw7zsyQSZjfYprdoEghzWYfgk27yEnZyNMV90HfD70ehdfe2nCIa05LV54pzt1UnIaXy8N97vH9f5oACyKZGz-sFABNuPUblrh173DrGZcf5RGfqFxGdQF4eFCRUx9Fqw_jysZO2JU3rVL7lkpMWqMgXeik7B8tuWqkW7n6LXPlBpJPC3Oie2hbdt9YcejPK7s/s400/PXL_20210623_110342320.jpg"/></a></div>
<p>
The traditional appeal of arcade sticks doesn't mean that things are standing still. Some new stick layouts have emerged over the years, the most popular of them probably being the hitbox layout, which ditches the actual joystick and instead uses four buttons for the direction inputs. The large button at the bottom is the jump button and it's meant to be operated by either your left or right thumb. This layout seems best suited for 2D games like Street Fighter. You can see <a href="https://www.printables.com/model/133138-hitbox-layout-fightstick">my take</a> on this control scheme below.
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVCklYrvumg8FMu9kO9mCZcYsDvInfrxkl12DeUx3oyKEpx7lnh2YgOppJvMyxr-uU4Ws7anyjtfcry-bqglPPgxClkf1WEBVWkOvpgYZx2lWUfpIo16k89D79eF07C07mG6MrPyZuYmjJ3_INFTOqOmigf3hqpTL1hUDNNe32DVorgiFyyLmvBa6fgX2HGZrveBI/s4032/PXL_20210618_153428669.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVCklYrvumg8FMu9kO9mCZcYsDvInfrxkl12DeUx3oyKEpx7lnh2YgOppJvMyxr-uU4Ws7anyjtfcry-bqglPPgxClkf1WEBVWkOvpgYZx2lWUfpIo16k89D79eF07C07mG6MrPyZuYmjJ3_INFTOqOmigf3hqpTL1hUDNNe32DVorgiFyyLmvBa6fgX2HGZrveBI/s400/PXL_20210618_153428669.jpg"/></a></div>
<p>
Another layout that uses buttons instead of the joystick is the mixbox layout. It uses keyboard keys in a more familiar WASD shape for the direction inputs. In my opinion it's better for 3D fighters like Virtua Fighter and Tekken than the hitbox layout. Here's <a href="https://www.printables.com/model/133140-mixbox-layout-fightstick">my version</a>.
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPycnXT3shyv8CATLStphgSGnTLklNvAvF2W34lR4-SdNZFyx3LW84leUJ0B_EK3FMd46JwEaajhsS7LFhDSpSFh6tdPRIGnJIXdUyi69kzvxablGoiK9pBCSNPmxBqE0tVaPFHqqmcBmxF7h1NLooC4BGmocU1vrkRix5A75pFfuFBzL-N3hjSy8lq35GkI3SCpQ/s3776/PXL_20210511_205015942b.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="2832" data-original-width="3776" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPycnXT3shyv8CATLStphgSGnTLklNvAvF2W34lR4-SdNZFyx3LW84leUJ0B_EK3FMd46JwEaajhsS7LFhDSpSFh6tdPRIGnJIXdUyi69kzvxablGoiK9pBCSNPmxBqE0tVaPFHqqmcBmxF7h1NLooC4BGmocU1vrkRix5A75pFfuFBzL-N3hjSy8lq35GkI3SCpQ/s400/PXL_20210511_205015942b.jpg"/></a></div>
<p>
In addition to new stick layouts, people have also started putting alternative parts in their sticks. One move that's obvious in retrospect is to try using mechanical keyboard switches instead of the traditional arcade buttons. There are many different keyboard switches to choose from and they also allow the fightstick case to be much slimmer. Here's my attempt at a hitbox-layout controller that uses Kailh low profile keyboard switches and is just 14 mm thick (I call it <a href="https://www.printables.com/model/133139-slimbox-hitbox-layout-low-profile-fightstick">the Slimbox</a>).
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWYSNrZRR2O-KPvJ0pmKvdfPyFl4QKYmcqO8bmZ3YzWXd9nL5eZsoywVFAWOVz-sf6zanSSqqxpWarI71EMOZ7d57AUanNbzhaQ13zL5Yghh5-7RjbZ08mRCTM1-fEj8JcT8Jc42vTXYT-hrBr4NA-QNJMLRc-LNp3M3O8H4LagHsyssx64oRSQ2smPtvRhHph3HA/s4032/PXL_20210607_204754658.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWYSNrZRR2O-KPvJ0pmKvdfPyFl4QKYmcqO8bmZ3YzWXd9nL5eZsoywVFAWOVz-sf6zanSSqqxpWarI71EMOZ7d57AUanNbzhaQ13zL5Yghh5-7RjbZ08mRCTM1-fEj8JcT8Jc42vTXYT-hrBr4NA-QNJMLRc-LNp3M3O8H4LagHsyssx64oRSQ2smPtvRhHph3HA/s400/PXL_20210607_204754658.jpg"/></a></div>
<p>
Similarly, here's a mixbox-layout version of the same idea (<a href="https://www.printables.com/model/133133-slimbox-m-mixbox-layout-low-profile-fightstick">Slimbox M</a>).
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr-UY0o9p3CQB-y-_Ad5zCtXIDrW-jQqB1GsL-kNOGHOvnyDcTVf2gjHV-dxxLL1lXuwdRhtD93vj-NL6fKvxKoZ6-u5gCMyH_toShu-PAT8K8aTrAvPHDH2cgDmyIna37vPtn4SlQH-_Jl_jwPzPtuosHpmItlhuB_6X9T2ZzEgfpnbiGIDUcQmyU9OtFRsXdtQM/s4032/PXL_20210705_225330427.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr-UY0o9p3CQB-y-_Ad5zCtXIDrW-jQqB1GsL-kNOGHOvnyDcTVf2gjHV-dxxLL1lXuwdRhtD93vj-NL6fKvxKoZ6-u5gCMyH_toShu-PAT8K8aTrAvPHDH2cgDmyIna37vPtn4SlQH-_Jl_jwPzPtuosHpmItlhuB_6X9T2ZzEgfpnbiGIDUcQmyU9OtFRsXdtQM/s400/PXL_20210705_225330427.jpg"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com1tag:blogger.com,1999:blog-5743520447405866726.post-56391311551381989052021-01-27T22:33:00.005+01:002022-07-07T21:28:03.323+02:00Bluetooth trackball Mark II<p>I made a Bluetooth trackball in which all the electronics are inside the ball. The ball is the entire trackball. Here it is in action:</p>
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" youtube-src-id="QbE3H4vglHw" width="480" height="270" src="https://www.youtube.com/embed/QbE3H4vglHw"></iframe></div>
<p>Inside the ball there's a microcontroller and a set of sensors that together with some clever algorithms allow the microcontroller to know the ball's absolute orientation in 3D. When the ball is rotated, it sends the appropriate commands to the computer over Bluetooth to move the mouse cursor. Oh, and the keyboard in the video is a completely separate USB device, it's only used for mouse clicks and doesn't interact with the ball in any way.</p>
<p>This is actually the second iteration of the project. While I was very proud of <a href="https://blog.jfedor.org/2019/06/bluetooth-trackball-with-all.html">my previous attempt</a>, it had some undeniable shortcomings and was generally a proof-of-concept quality device. This new version improves upon it in many regards, to the point where I think it could possibly be used on a day to day basis as a replacement for your regular mouse. Specific features include:</p>
<ul>
<li>an nRF52840 chip along with LSM6DS33 accelerometer/gyroscope and LIS3MDL magnetometer</li>
<li>a wirelessly rechargeable 500 mAh battery</li>
<li>battery level reporting over Bluetooth</li>
<li>more robust "up" calibration</li>
<li>fully sealed construction allowing for smooth rolling of the ball</li>
</ul>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMqfDF67cCnxISd55Z4yp1-qBs8I2MYLtYBQWMLVdZdqVMnIM7stdqHe56PHgNSTlDTlJuiYn3W4hyAac1eQrBdIzPWv_srGq4g7VOLI5MRB0Wkhgic0kepzBibmTTljf7IYHvgQ5OFxpo8Ok4/s4032/PXL_20210127_204615105.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMqfDF67cCnxISd55Z4yp1-qBs8I2MYLtYBQWMLVdZdqVMnIM7stdqHe56PHgNSTlDTlJuiYn3W4hyAac1eQrBdIzPWv_srGq4g7VOLI5MRB0Wkhgic0kepzBibmTTljf7IYHvgQ5OFxpo8Ok4/s400/PXL_20210127_204615105.jpg"/></a></div>
<p>I used Adafruit's <a href="https://www.adafruit.com/product/4516">Feather nRF52840 Sense</a>, it has all the necessary sensors onboard. The other components are a lipo battery, a wireless charging coil and two reed switches, one of which is connected to the board's "En" pin, allowing us to turn the device off with an external magnet, the other is connected to a GPIO pin and is used to trigger the "up" calibration.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh39P8ERCnhfzoWVENzFba-3b81W6MjnZiJun9IhmIjKXAWWJ4XPO3GnmDvLoQ3O6IABO5wOWaf7wnpphWtz1pwRPbf0NYGtk7HR1lb1EffWtRVPnvbaa8S1DGH3TMSXcUawc90mNbA6D51wPYe/s4032/PXL_20210122_161325536.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh39P8ERCnhfzoWVENzFba-3b81W6MjnZiJun9IhmIjKXAWWJ4XPO3GnmDvLoQ3O6IABO5wOWaf7wnpphWtz1pwRPbf0NYGtk7HR1lb1EffWtRVPnvbaa8S1DGH3TMSXcUawc90mNbA6D51wPYe/s400/PXL_20210122_161325536.jpg"/></a></div>
<p>The ball is 65 mm in diameter and is made of two 3D printed halves. After putting the electronics inside I glued the two halves together and smoothed the surface by progressing through increasingly finer grits of sandpaper. It rolls pretty smoothly on 2.5 mm zirconium oxide bearing balls, though it's still admittedly not as smooth as a real trackball. I made a few bases in various shapes for the ball to roll on, they are just pieces of 3D printed plastic and don't have any electronics in them.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFr_VO2hp_n-YbZjhVlzNMTVDUNOXtcGjBVtNnvDZKY0NzDjrwqU8odldfBb9vJ7gUP9jz28QchyoSJwSy8tJYNp-7MGg9b3tT9g579KdO7SQDpt1F9wKxEYTyDzKhu8FRpRf9O65OOhU9NL7p/s4032/PXL_20210127_204752319.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFr_VO2hp_n-YbZjhVlzNMTVDUNOXtcGjBVtNnvDZKY0NzDjrwqU8odldfBb9vJ7gUP9jz28QchyoSJwSy8tJYNp-7MGg9b3tT9g579KdO7SQDpt1F9wKxEYTyDzKhu8FRpRf9O65OOhU9NL7p/s400/PXL_20210127_204752319.jpg"/></a></div>
<p>To charge the battery inside the ball I also made a special base that has a wireless charging coil inside and is powered with USB (or any 5V source). It also has a strategically placed magnet that can be used to trigger one of the two reed switches inside the ball, one will turn the device off, the other allows for setting the logical "up" directon of the trackball (by itself the trackball doesn't know which direction should move the mouse cursor up, so you can set it by putting a magnet near one of the reed switches and rotating the ball around the vertical axis).</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSjkiVN2g6_I80xB6BkXC8CnLxjwU8ArOt_BsL1YTW9Wx-I9X4SazwZ8ea0Vb28PQYMv7fT48KT99AFTZ7QuWeKaD0E9CbNUvk8Xv1OuFp8yOIufNnMQTGVqg8NXYk9amzE_IA5T232kEnpZFr/s4032/PXL_20210127_204324867.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSjkiVN2g6_I80xB6BkXC8CnLxjwU8ArOt_BsL1YTW9Wx-I9X4SazwZ8ea0Vb28PQYMv7fT48KT99AFTZ7QuWeKaD0E9CbNUvk8Xv1OuFp8yOIufNnMQTGVqg8NXYk9amzE_IA5T232kEnpZFr/s400/PXL_20210127_204324867.jpg"/></a></div>
<p>The Arduino code and 3D models are <a href="https://github.com/jfedor2/trackbowl-mk2">on GitHub</a>.Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com17tag:blogger.com,1999:blog-5743520447405866726.post-3606426506747879042020-11-06T18:08:00.004+01:002022-07-07T21:27:50.190+02:00Dactyl Manuform build log<p>I made an ergonomic split keyboard using the Dactyl Manuform design, specifically the 5x6 version. I'm going to describe the process in the hope that it will be useful to someone considering making one. Here's what the final product looks like:</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidOc9lmo0NBXDLRqshXGEvLZyWkMGV4O29aVpLFtjRQIG9V7S3ySA8Nhbp-HxbeDns-4RNDWXQZxyXRyAy5V1D-vYloQQ30Mxn6dKp4eHxLPvxnQedIRMqCryO-djokzER8QYTpZ8aL3bsbdnt/s4032/PXL_20201104_212007417.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidOc9lmo0NBXDLRqshXGEvLZyWkMGV4O29aVpLFtjRQIG9V7S3ySA8Nhbp-HxbeDns-4RNDWXQZxyXRyAy5V1D-vYloQQ30Mxn6dKp4eHxLPvxnQedIRMqCryO-djokzER8QYTpZ8aL3bsbdnt/s400/PXL_20201104_212007417.jpg"/></a></div>
<p>The <a href="https://github.com/tshort/dactyl-keyboard">Dactyl Manuform</a>, made by Tom Short, is a modification of the original <a href="https://github.com/adereth/dactyl-keyboard">Dactyl keyboard</a> design by Matthew Adereth. Matthew has given <a href="https://www.youtube.com/watch?v=uk3A41U0iO4">an entertaining talk on his design process</a>. It won't really help with building the keyboard, but it has some nice bits on keyboard history in general.</p>
<p>The keyboard is controlled by an Arduino Pro Micro (one in each half) which is running the <a href="https://qmk.fm/">QMK firmware</a>. This firmware is used by many keyboards, both hand-made and mass-produced and it has several useful features and allows you to customize the keyboard to a much greater extent compared to what's possible on a normal one.</p>
<p>Let's get to it. First we need to decide on the general shape of the keyboard and 3D print the case (or have someone 3D print it for us). I went with 5x6, meaning 5 rows and 6 columns of keys, which translates to having a row for the 0-9 keys, but not for the function keys. The fifth row only has two keys and there's also a 6-key thumb cluster. The 3D models are generated by a Clojure program that outputs a .scad file that is then converted to STL using OpenSCAD. Things like the number of rows and columns and the angles are all configurable in the Clojure code. If you don't want to mess with Clojure, there's an <a href="http://dactyl.siskam.link/">online generator</a> that lets you customize some things and gives you a .scad file.</p>
<p>Here's what it looked like after printing in my case:</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYuRqX4X_R2iX6vMu2OhJdbEyM7X4WeIIZx3mBqHT5HPG-WgjNA8udJOD_bbncZLtEG6SGaBOjAsdFUCXaMZVoXvwAX3rRFUgy8vj4q4E5zKeESuugbEk86uM07BwP6hPEnkpaajxCqZcOUv8I/s4032/PXL_20201028_165343707.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYuRqX4X_R2iX6vMu2OhJdbEyM7X4WeIIZx3mBqHT5HPG-WgjNA8udJOD_bbncZLtEG6SGaBOjAsdFUCXaMZVoXvwAX3rRFUgy8vj4q4E5zKeESuugbEk86uM07BwP6hPEnkpaajxCqZcOUv8I/s400/PXL_20201028_165343707.jpg"/></a></div>
<p>I've made some modifications to the design, fixing some issues and changing the holes for the ports to circular ones (so that they can easily be used with panel-mount sockets). I also added a hole for a reset button, which is useful when programming the thing. You can get my STL files <a href="https://www.thingiverse.com/thing:4644610">on Thingiverse</a>. People often cut the bottom plate from acrylic or even metal, but I just 3D printed it like the rest of the case. I also didn't use heat set inserts and just went with wood screws. Oh, and I really recommend using Cura with tree supports when printing the case. Normally I use PrusaSlicer for everything, but in this case the supports it generated were practically impossible to remove. Printing each half took about 20 hours on my Prusa MK3S.</p>
<p>In addition to the case, here are the parts that I used:</p>
<ul>
<li>Arduino Pro Micro (2x)</li>
<li>Gateron Brown switches (64x)</li>
<li>DSA profile keycaps (60x 1u and 4x 1.5u)</li>
<li>1N4148 diodes (64x)</li>
<li>panel-mount micro USB socket (2x)</li>
<li>panel-mount 3.5mm TRS socket (2x)</li>
<li>panel-mount momentary switch (2x)</li>
<li>some hookup wire, 24 AWG</li>
<li>3x10mm wood screws for attaching the bottom plate (10x)</li>
</ul>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZtBo2KwhByEBfJoCDl6cjKN_QQ98YmzVM3ivVLeKFi9uekfaDC81kn5XUoClwGWIXdOPfvMmNZRxB72TsT5INRMoFrV5Q1PjH2Z_lOnthQvcv9O53yPPV9RJn6XZ-GJYqMzREL1lDaD1zzPu4/s3297/PXL_20201105_180155494.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="3297" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZtBo2KwhByEBfJoCDl6cjKN_QQ98YmzVM3ivVLeKFi9uekfaDC81kn5XUoClwGWIXdOPfvMmNZRxB72TsT5INRMoFrV5Q1PjH2Z_lOnthQvcv9O53yPPV9RJn6XZ-GJYqMzREL1lDaD1zzPu4/s400/PXL_20201105_180155494.jpg"/></a></div>
<p>Then we need to actually wire the thing. To avoid having to use a separate wire going to the controller from every key, a <a href="https://en.wikipedia.org/wiki/Keyboard_matrix_circuit">matrix circuit</a> is used, meaning the keys are arranged into rows and columns and there's a diode connected to every key. There's a <a href="https://github.com/tshort/dactyl-keyboard#alternative-row-driven-wiring-diagram-for-promicro">wiring diagram</a> on Tom Short's repository, but it's somewhat confusingly described as "alternative". The alternative one is the one you want.</p>
<p>First, we put the switches into the case. They are only press-fit mounted so be careful when removing keycaps as you can easily pull the switch out along with the keycap. Here's what it looked like before any soldering:</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZd3Vo5jo-n4fqdt1sfzfwvZXzkhYfTHvDiZ3yBChczaBNYOaphPMxl6S5d2Rkvydahzf6GpdUf4hcbLBTmCea7JFm-TcdfR06UOv1LbziK9cmDSMfyALx3-jywZ7IFghvusgzmBH_6wFc8Dz4/s4032/PXL_20201028_171253474.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZd3Vo5jo-n4fqdt1sfzfwvZXzkhYfTHvDiZ3yBChczaBNYOaphPMxl6S5d2Rkvydahzf6GpdUf4hcbLBTmCea7JFm-TcdfR06UOv1LbziK9cmDSMfyALx3-jywZ7IFghvusgzmBH_6wFc8Dz4/s400/PXL_20201028_171253474.jpg"/></a></div>
<p>For the rows I used a method where no additional wire is required and the diode leads are used to connect one key to the next. Pay attention to the orientation of the diodes!</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEdoKBR0e9Rb7-cNV9HAMssgYP4BS3VYQimM4ZNjP-VOdzNOLvtHn40MPW_b1mS-L6wLXPPnjAD-q9iIiyB6riHRQBmMdv2eRD4-rKD-yJ7kK7MbhqE2RVrSn-wbSNzCXQZ-GqW3EJ9_w0562Q/s4032/PXL_20201028_195035366.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEdoKBR0e9Rb7-cNV9HAMssgYP4BS3VYQimM4ZNjP-VOdzNOLvtHn40MPW_b1mS-L6wLXPPnjAD-q9iIiyB6riHRQBmMdv2eRD4-rKD-yJ7kK7MbhqE2RVrSn-wbSNzCXQZ-GqW3EJ9_w0562Q/s400/PXL_20201028_195035366.jpg"/></a></div>
<p>Then I wired the columns (please excuse my poor soldering skills):</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc2BoFmFtu1oypvXC2Mw6FTQg7NSDK1dS-KH-5OCIsCTQHTIWW7nUEywK2gqkNXcOvA0u-u03OJ59bg06DsPj8-B-fHEpWCO7aTUDWDuQ2hgvbxrnVSv_BU9yUYKSeXJcuFAgl1Nfgk6q5NCPj/s4032/PXL_20201028_224216516.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc2BoFmFtu1oypvXC2Mw6FTQg7NSDK1dS-KH-5OCIsCTQHTIWW7nUEywK2gqkNXcOvA0u-u03OJ59bg06DsPj8-B-fHEpWCO7aTUDWDuQ2hgvbxrnVSv_BU9yUYKSeXJcuFAgl1Nfgk6q5NCPj/s400/PXL_20201028_224216516.jpg"/></a></div>
<p>Then the rows and columns need to be wired to the right pins on the Arduino:</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixgQuDLb5Kc9iimfCLhEAhWGUpE5_DCMgsn8Y85GIohba0rALwO6JY37_ssjsLP9qbAUjUI3A_43mzWv8T0M_GzU49XEWI1rjlSmlR3trn09CLunSz64401ojlwFziNuDfAgx-0B2Ch2O3KRWV/s4032/PXL_20201029_224422740.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixgQuDLb5Kc9iimfCLhEAhWGUpE5_DCMgsn8Y85GIohba0rALwO6JY37_ssjsLP9qbAUjUI3A_43mzWv8T0M_GzU49XEWI1rjlSmlR3trn09CLunSz64401ojlwFziNuDfAgx-0B2Ch2O3KRWV/s400/PXL_20201029_224422740.jpg"/></a></div>
<p>The 3.5mm socket and the reset button also need to be wired to the Arduino and the whole thing needs to be repeated for the other side:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3kI-aHGy26vZ0hLIxFMBmwYFpQQchpQG8XDRYk2luHykNclDArmu5lSFFlBbrdFUQMLGcq-HEj0KVt3-jaeNbhBbW7wQx6vP2Q0vKlbHume9yEN7h-UOFZHjw2Dzwb-lTyM61hnmDCKML9uZV/s4032/PXL_20201103_230725683.jpg" style="padding: 1em 0; text-align: center; "><img alt="" border="0" width="200" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3kI-aHGy26vZ0hLIxFMBmwYFpQQchpQG8XDRYk2luHykNclDArmu5lSFFlBbrdFUQMLGcq-HEj0KVt3-jaeNbhBbW7wQx6vP2Q0vKlbHume9yEN7h-UOFZHjw2Dzwb-lTyM61hnmDCKML9uZV/s200/PXL_20201103_230725683.jpg"/></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9FTtSMJMrmRU2NvdNiUCRpf00f_Y3LHheDBOG6W183QN3_PGGIEFTQpAs_rgdmfaCz2EexJaEpnP62zWjU7cEw7nYDDz1yNIxQqRXpJy2iN8lnlVBGyDqHUUxlvceieX7ICAg-bjBIIINAt5F/s4032/PXL_20201104_162040137.jpg" style="padding: 1em 0; text-align: center; "><img alt="" border="0" width="200" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9FTtSMJMrmRU2NvdNiUCRpf00f_Y3LHheDBOG6W183QN3_PGGIEFTQpAs_rgdmfaCz2EexJaEpnP62zWjU7cEw7nYDDz1yNIxQqRXpJy2iN8lnlVBGyDqHUUxlvceieX7ICAg-bjBIIINAt5F/s200/PXL_20201104_162040137.jpg"/></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqlrJAz3l0bMb7N071TWSzN3EhTnVVEI7gYvbV0vDcWX6BYffYaQbCnlBoo4D7M9E2JmOm2akgjGGi0DENZ0sFW0_l91y-L8VzOXyZA6A7LPB9uGDwjvLd9T1myOoJ__WaSmSrnMANttH_8sJb/s4032/PXL_20201104_191425877.jpg" style="padding: 1em 0; text-align: center; "><img alt="" border="0" width="200" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqlrJAz3l0bMb7N071TWSzN3EhTnVVEI7gYvbV0vDcWX6BYffYaQbCnlBoo4D7M9E2JmOm2akgjGGi0DENZ0sFW0_l91y-L8VzOXyZA6A7LPB9uGDwjvLd9T1myOoJ__WaSmSrnMANttH_8sJb/s200/PXL_20201104_191425877.jpg"/></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCQW0kFUFgZybNWpIW8frKss8pyYhVFzNec7cPvo2lHzr1tPPeBSH2DscuWYb0dDpJFULoyml-73dRycy3SzPOcdQ_QFhvuO7bTiXXaBR1T3zyi10k7qrCQ4pA_ILp2x0k1HIOoUFbofezi3ic/s4032/PXL_20201104_195905886.jpg" style="padding: 1em 0; text-align: center; "><img alt="" border="0" width="200" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCQW0kFUFgZybNWpIW8frKss8pyYhVFzNec7cPvo2lHzr1tPPeBSH2DscuWYb0dDpJFULoyml-73dRycy3SzPOcdQ_QFhvuO7bTiXXaBR1T3zyi10k7qrCQ4pA_ILp2x0k1HIOoUFbofezi3ic/s200/PXL_20201104_195905886.jpg"/></a></div>
<p>Then we mount the USB socket, connect it to the Arduino and try to squeeze everything inside the case. In theory the case includes a holder for the Arduino board, but I ended up not using it. With all the wires the board doesn't move around too much. I put some foam between the switches and the Arduino to avoid shorts.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsV8hMWz_JZ9QFEFRB9vZOOFZ0x0e-V4GaaO8agaSiZIQWCPaLl-wlI4nS-TiB2bEAWKqk20ONuyKM_wHBioR80SLolFS5royYn9mKO_pryQWTh-9V2OiGfS51ZacOH45Inv5kJA2EGhd9Br9R/s4032/PXL_20201104_205219644.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsV8hMWz_JZ9QFEFRB9vZOOFZ0x0e-V4GaaO8agaSiZIQWCPaLl-wlI4nS-TiB2bEAWKqk20ONuyKM_wHBioR80SLolFS5royYn9mKO_pryQWTh-9V2OiGfS51ZacOH45Inv5kJA2EGhd9Br9R/s400/PXL_20201104_205219644.jpg"/></a></div>
<p>Before attaching the bottom plates, test the thing! Suprisingly in my case it worked the first time with no issues.</p>
<p>A quick note on how the two halves work together. Each half of the keyboard has an Arduino Pro Micro board that's wired to the key matrix. In theory you could just connect each half separately to the computer via USB and it would work. But then we'd end up using two USB ports just for the keyboard and we wouldn't be able to do some clever tricks with the layout that require communication between the two halves. So instead the way it works is only one half is connected to the computer through USB and the two halves are connected to each other using a serial interface - that's what the 3.5mm jacks are for (BTW, don't connect or disconnect the 3.5mm cable while the keyboard is connected over USB):</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDtIWCChCKUXqZdoIkNAgo1z814qvbVXj9oXSIE4TrOlpy5tShkVWy6J1_EzkVoQjETsTc8Civ_46MW5uc1YNqKdhsZ3vYtNKUhYatDb-52NJVxIMkXH4ftOP4BwrNE35nDiFAYUiQ5cliq6_T/s4032/PXL_20201104_212224600.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDtIWCChCKUXqZdoIkNAgo1z814qvbVXj9oXSIE4TrOlpy5tShkVWy6J1_EzkVoQjETsTc8Civ_46MW5uc1YNqKdhsZ3vYtNKUhYatDb-52NJVxIMkXH4ftOP4BwrNE35nDiFAYUiQ5cliq6_T/s400/PXL_20201104_212224600.jpg"/></a></div>
<p>How does the Arduino know if it's the left or the right half? By default the USB cable is supposed to be connected to the left half so that's how it decides: if USB is connected, then it knows it's the left half, otherwise it's the right half. I didn't like that very much, I wanted the freedom to connect USB to any of the halves. Fortunately that variant is fully supported, you just have to store the left/right identity in EEPROM when flashing the board. To achieve that I commented out the <tt>#define MASTER_LEFT</tt> in <tt>keyboards/handwired/dactyl_manuform/5x6/keymaps/default/config.h</tt> and uncommented <tt>#define EE_HANDS</tt>. Then to flash the left half I do:</p>
<p><tt>make handwired/dactyl_manuform/5x6:default:avrdude-split-left</tt></p>
<p>And to flash the right part I do:</p>
<p><tt>make handwired/dactyl_manuform/5x6:default:avrdude-split-right</tt></p>
<p>When the software tells you to reset the board, you double tap the reset button quickly. If you don't want to mess around with compiling the firmware yourself and generally want to avoid the command line, there's this thing called the <a href="https://qmk.fm/toolbox/">QMK Toolbox</a> that has a nice GUI.</p>
<p>And now for the fun part, defining your own layout! There's an <a href="https://config.qmk.fm/">online configurator</a> where you can define your key mapping and download a JSON configuration file. Or you can modify the <tt>keymap.c</tt> file in <tt>keyboards/handwired/dactyl_manuform/5x6/keymaps/</tt>. If you go the JSON route, just delete the keymap.c file and put a keymap.json file in the same directory. Then flash the firmware using the commands above. Or if you're using the QMK Toolbox, the online generator can compile the thing for you.</p>
<p>I hope this quick report helps someone, have fun if you decide to build one yourself. I really think it's a nice project!</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Sugu5QdydrExYBWt0HhzChQ-yy8ft5hAQa4ylC_IQKJ1RcyQPqbzTF7Fi5Ocg0MnPFc6iJ4w7-MVlWPoaYQgGNtcCWt5ijvl9QgIQDC9Fhl3eauxrlKnT8hnTrufTbZXK9JmKyPF_4tFSL-b/s4032/PXL_20201104_212327615.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Sugu5QdydrExYBWt0HhzChQ-yy8ft5hAQa4ylC_IQKJ1RcyQPqbzTF7Fi5Ocg0MnPFc6iJ4w7-MVlWPoaYQgGNtcCWt5ijvl9QgIQDC9Fhl3eauxrlKnT8hnTrufTbZXK9JmKyPF_4tFSL-b/s400/PXL_20201104_212327615.jpg"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com6tag:blogger.com,1999:blog-5743520447405866726.post-26109848101812069012020-10-18T14:46:00.002+02:002021-02-03T22:55:31.720+01:00Lean back to scroll<p>You know those days when lifting a finger to scroll a website seems like to much of an effort? No, of course not, me neither. But just in case I made this so I can scroll just by leaning back in my chair:</p>
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" youtube-src-id="mv5tD-7EkHM" width="400" height="322" src="https://www.youtube.com/embed/mv5tD-7EkHM"></iframe></div>
<p>If you look closely there's Adafruit's <a href="">Feather nRF52840 Sense</a> board attached to the back of the chair. It uses the onboard sensors to figure out the angle of the chair's back and if it's over a threshold it sends scroll down events to the computer (using the standard Bluetooth mouse protocol so it works with any OS). To set the "zero" position you press the "user switch" button on the board.</p>
<p><a href="https://github.com/jfedor2/scroll-chair">Here's the Arduino code.</a>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHJdpx1M7gZOe_PCrbuH_UTQrxRVVt1JP7vLI8Uplv-XNmf84IP8X9KzDXfAovPlNsFjBU6zyXp4ThCd07KWoqpETLXYQZBFXCWWdaPMQnOUjD-6T04n07cFL9ha6uQ_y7YTyhDwyAx7cT70hU/s4032/PXL_20201004_151429752.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHJdpx1M7gZOe_PCrbuH_UTQrxRVVt1JP7vLI8Uplv-XNmf84IP8X9KzDXfAovPlNsFjBU6zyXp4ThCd07KWoqpETLXYQZBFXCWWdaPMQnOUjD-6T04n07cFL9ha6uQ_y7YTyhDwyAx7cT70hU/s400/PXL_20201004_151429752.jpg"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-68564017845682642502020-09-27T18:50:00.001+02:002021-02-03T22:55:44.680+01:00Hat mouse<p>I've been playing around with orientation sensors and Bluetooth HID recently. Today I'd like to show you what is perhaps my most practical application of those yet. I made a head mouse, also known as an air mouse, or in my case, a hat mouse:</p>
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" youtube-src-id="aJb6M_2izWQ" width="400" height="322" src="https://www.youtube.com/embed/aJb6M_2izWQ"></iframe></div>
<p>The device is attached to a hat and you move your head around to move the mouse cursor on the screen. It uses the standard Bluetooth mouse protocol so it works with Windows, Mac and Linux with no additional software running on the computer. The board used is Adafruit's <a href="https://www.adafruit.com/product/4516">Feather nRF52840 Sense</a>. The way it works is it reads accelerometer, gyroscope and magnetometer data, puts it through a sensor fusion algorithm to get orientation and then uses the yaw and pitch values to position the mouse cursor on the screen. It uses absolute cursor positioning so any given head orientation corresponds to a fixed cursor position on the screen. To reset the center position, you press the "user switch" button on the board.</p>
<p><a href="https://github.com/jfedor2/hat-mouse">Here's the Arduino code.</a> In addition to the Feather board we need some way to power it. I used <a href="https://www.adafruit.com/product/1578">this lipo battery</a>, but the board can also be powered over the USB port so a small power bank could work as well.</p>
<p>As with some of my previous custom devices that work as a mouse, unfortuntely the hat mouse has no way of performing button clicks yet. In the video above I'm using a separate USB foot switch for clicking. Depending on the movement limitations of the user, something like a sip-and-puff switch might be more appropriate (same goes for the orientation reset button that's currently located on the board). The Feather nRF52840 Sense board has a lot of sensors in addition to those that we're currently using for the orientation. Perhaps the pressure sensor or the light sensor or even the microphone could be used to make entirely head-operated switches. I have some ideas, but I decided to treat that as a separate project.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlsi06unPsfAvMryJ3WWwhDHPB4W6U2lXy3fu-AbhVlar4SgTmwTslO7WmN539trLueq9JsFN7q-g6g0WGKdQlxIAzjOyiLGpLERvbgKNs8tsFwgOalYNCNK0V2Iskxyu0ilTtsO1C0ZkezmtI/s3913/PXL_20200927_161906505.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="3024" data-original-width="3913" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlsi06unPsfAvMryJ3WWwhDHPB4W6U2lXy3fu-AbhVlar4SgTmwTslO7WmN539trLueq9JsFN7q-g6g0WGKdQlxIAzjOyiLGpLERvbgKNs8tsFwgOalYNCNK0V2Iskxyu0ilTtsO1C0ZkezmtI/s400/PXL_20200927_161906505.jpg"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-12713103493936852422020-09-21T21:50:00.001+02:002021-02-03T22:55:57.330+01:00Plotting sensor data with MS Paint and Bluetooth HID<p>I have recently discovered that the HID mouse protocol supports absolute cursor positioning in addition to the more common relative mode. I think that opens interesting possibilities, one of them being we can plot real-time charts in MS Paint with no additional software running on the computer, using just the standard Bluetooth mouse protocol:</p>
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" youtube-src-id="6ci6fllYJLU" width="400" height="322" src="https://www.youtube.com/embed/6ci6fllYJLU"></iframe></div>
<p>The board used above is Adafruit's <a href="https://adafruit.com/products/4516">Feather nRF52840 Sense</a>, which has Bluetooth LE and lots of sensors. On the video we're plotting readings from the accelerometer. The chart is drawn by simulating mouse and keyboard inputs (keyboard is used to clear the screen when we reach the right edge).</p>
<a href="https://github.com/jfedor2/ms-paint-chart">Here's the Arduino code.</a>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFjHVGceOh0oRaeiipRQ8gC0suNGjyEDMYxwFh7j4AkoQCwv_QR38-kUKAF3JtbJ0g0eZ88GhfhW6mokF1voMiQKASNbwFJBQwAHtzRP7gUzWHN8HpNxFHLFU8R6NfetWnVRSH30xro-OA0E2c/s1920/ms-paint-plotting-sensor-data.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="1040" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFjHVGceOh0oRaeiipRQ8gC0suNGjyEDMYxwFh7j4AkoQCwv_QR38-kUKAF3JtbJ0g0eZ88GhfhW6mokF1voMiQKASNbwFJBQwAHtzRP7gUzWHN8HpNxFHLFU8R6NfetWnVRSH30xro-OA0E2c/s400/ms-paint-plotting-sensor-data.png"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-89117174502463285082020-09-20T19:22:00.002+02:002021-02-03T22:56:23.028+01:00USB "rubber ducky" with mouse input<p>Perhaps you're familiar with a type of device commonly referred to as a <em>USB rubber ducky</em>. It's a seemingly innocent device that looks like a regular USB drive, but when connected to a computer, it acts as a USB keyboard and sends malicious keystrokes to the victim's machine, as if a human typed them (but faster). The commands sent can download some unwanted software or open a reverse shell and do nasty stuff in general.</p>
<p>So I thought why stop at keyboard, why not also pretend to be a mouse, launch Paint and draw something funny:</p>
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" youtube-src-id="VckvC7uBdL4" width="400" height="322" src="https://www.youtube.com/embed/VckvC7uBdL4"></iframe></div>
<p>The main challenge here is that a regular mouse doesn't really know where the cursor is on the screen. It only sends relative position changes like "move the cursor 7 units to the right and 2 units down". Depending on the sensitivity setting on the user's system, it might correspond to a different distance in pixels. When you add mouse acceleration into the mix, it's not really practical to try and guess where the cursor will end up being.</p>
<p>But, as is turns out, the mouse HID protocol also allows for absolute cursor positioning and all the major desktop operating systems support this mode (perhaps because touchscreens and graphics tablets use it?). With that knowledge, the task becomes easy, as we can just say "move the cursor to position X, Y".</p>
<p>I used a Digispark with a modified version of Adafruit's <code>TrinketHidCombo</code> library for the demo above. <a href="https://github.com/jfedor2/usb-rubber-ducky-mouse">Here's the Arduino code.</a></p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhweKaN19itg3C9ji0L-bCRfTQSUulX63tzwZmc5YX1p59Sgxjd1sK4Ihowehm2Os7AHrWdPwe9nCDaGmOS0tdDVLSeLLZGGj7rKusgjRtq7KMB00k02iU7FZNzba_6Fz-70D8032E_fRG5TVUF/s2826/PXL_20200920_171338089.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="2119" data-original-width="2826" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhweKaN19itg3C9ji0L-bCRfTQSUulX63tzwZmc5YX1p59Sgxjd1sK4Ihowehm2Os7AHrWdPwe9nCDaGmOS0tdDVLSeLLZGGj7rKusgjRtq7KMB00k02iU7FZNzba_6Fz-70D8032E_fRG5TVUF/s400/PXL_20200920_171338089.jpg"/></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com3tag:blogger.com,1999:blog-5743520447405866726.post-89207563647192766902020-09-08T22:09:00.002+02:002021-02-03T22:56:34.759+01:00Human trackball<p>Remember <a href="https://www.youtube.com/watch?v=QjEsxCx-HrE" target="_blank">Logitech's April Fools' video</a> from 2017? The one where the gym ball works as a trackball? I made that for real:</p>
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" youtube-src-id="FprARCVnGL4" width="480" height="320" src="https://www.youtube.com/embed/FprARCVnGL4"></iframe></div>
<p>I did this as kind of a detour while working on the next version of my <a href="https://blog.jfedor.org/2019/06/bluetooth-trackball-with-all.html">Bluetooth trackball</a> from last year (stay tuned for that). I found <a href="https://www.aliexpress.com/item/33014422230.html">a board on AliExpress</a> that has the nRF52832 Bluetooth chip from Nordic, an MPU-9250 9DOF sensor, a built-in battery charging circuit and comes with a lipo battery attached. Originally a development board for a fitness bracelet, it looked like a pretty good match for my needs.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg94OD4rY0Rk3nvWoPFkkWyYrkv02Cm7AKSzibDQeW4OT7rPh37r7xT3Ai253M43fSk9qdqF-jJKO2Us-TOuBNIO5ZF2h1cgifadBXOIpwthbNhM3_e30G3oV_upkDeNAPNawajMWXMI4p37epl/s1958/NRF52832-MPU9250.jpg" style="display: block; padding: 1em 0; text-align: center;"><img alt="" border="0" width="400" data-original-height="1306" data-original-width="1958" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg94OD4rY0Rk3nvWoPFkkWyYrkv02Cm7AKSzibDQeW4OT7rPh37r7xT3Ai253M43fSk9qdqF-jJKO2Us-TOuBNIO5ZF2h1cgifadBXOIpwthbNhM3_e30G3oV_upkDeNAPNawajMWXMI4p37epl/s400/NRF52832-MPU9250.jpg"/></a></div>
<p>For this application I just attached the board to the gym ball using scotch tape (and tried to avoid sitting on it or crushing it by rolling the ball).</p>
<p>The software is derived from my previous IMU-based Bluetooth trackball attempt. This time I decided to do the sensor fusion algorithm in software - even though the MPU-9250 is better than the MPU-6050 because it has a magnetometer (3 more DOFs!), its onboard algorithm was not updated to make use of it - it still only uses the accelerometer and gyroscope. So I used <a href="https://github.com/adafruit/Adafruit_AHRS">Adafruit's library</a> implementing <a href="https://x-io.co.uk/open-source-imu-and-ahrs-algorithms/">Sebastian Madgwick's sensor fusion algorithm</a>. I also used Sandeep Mistry's <a href="https://github.com/sandeepmistry/arduino-nRF5">Arduino core for the nRF52832 chip</a> and his <a href="https://github.com/sandeepmistry/arduino-BLEPeripheral">BLEPeripheral library</a> for Bluetooth. I programmed the board using Nordic's <a href="https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK">nRF52 DK</a> development kit.</p>
<p>You can find the code <a href="https://github.com/jfedor2/human-trackball">here</a>. Also included is a sketch for calibrating the magnetometer that sends the data over Bluetooth serial (I used Adafruit's <a href="https://play.google.com/store/apps/details?id=com.adafruit.bluefruit.le.connect">Bluefruit Connect</a> app to read the data). And since the gym ball itself has no way of performing button clicks, I used a foot switch connected to a Digispark for clicking the mouse. A sketch for that is also included.</p>
<p>Even though it looks like a trackball, the ball works more like a joystick in this case: when you tilt it to the right, the cursor moves as long as the ball is kept in that position and stops moving when it is returned to the neutral starting position. Right now it's not really a practical mouse or trackball replacement, but I believe that with some fine tuning it might become a viable option. Another possibility would be to only use it for scrolling, not moving the cursor, which I haven't tested, but it should be an easy modification.</p>
<p>Can't wait for Logitech's next year April Fools' video!</p>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-6930313284352063452020-03-09T21:27:00.000+01:002020-03-09T21:33:19.275+01:00Bathroom occupancy monitor<p>Don't you hate it when you get up from your desk at work to go to the bathroom, only to find out that all the stalls are occupied? I did, so I made a website that shows the current status of each stall. It normally looks something like this:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUiVBsrnZhSDf4RBWKhUjlkDdhqzTiEY5LUG0-0uUSF3ORnCfpY5QnMiAcgAo1kg9t6lZO-KVC63jHZuQfgt2VnDREYYsAtvJHVcHKFGUD1FYZkzTqcJQePp24gQwOzpkNqnGZc5EyTzx4AIGJ/s1600/toilet-website.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUiVBsrnZhSDf4RBWKhUjlkDdhqzTiEY5LUG0-0uUSF3ORnCfpY5QnMiAcgAo1kg9t6lZO-KVC63jHZuQfgt2VnDREYYsAtvJHVcHKFGUD1FYZkzTqcJQePp24gQwOzpkNqnGZc5EyTzx4AIGJ/s320/toilet-website.png" width="320" height="279" data-original-width="1080" data-original-height="941" /></a></div>
<p>To make this possible, I installed a 433 MHz door/window sensor on each stall door. Somewhere nearby I put an ESP8266 module with a 433 MHz receiver board. Each time a stall door is locked or unlocked, the module gets a signal from the sensor and passes it on to a Firebase cloud function that saves the current state and timestamp in a database. Finally there's a website that reads the database and displays the current status for everyone to see.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEMa73DGGAaDix-QUGvnro-G8VF3t7XFhP8LkppcfYhWqt1vuwCz4roviN2hrjK3Q-lGRoTDItPZNGDCp3bXom4ETMfoFDhYxlZe7p9c7ZdReESRt3EBEMm989nCQKxLrmnEC_dU4BwEFalM2R/s1600/toilet-diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEMa73DGGAaDix-QUGvnro-G8VF3t7XFhP8LkppcfYhWqt1vuwCz4roviN2hrjK3Q-lGRoTDItPZNGDCp3bXom4ETMfoFDhYxlZe7p9c7ZdReESRt3EBEMm989nCQKxLrmnEC_dU4BwEFalM2R/s480/toilet-diagram.png" width="480" height="166" data-original-width="960" data-original-height="331" /></a></div>
<p>Even though the sensors I used are normally meant to detect when a door (or window) is <i>opened</i>, what I really wanted to detect in this case is whether the doors are <i>locked</i>. I achieved that using a zip tie and a neodymium magnet attached to the door lock:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC470ptYoXn2sZ5VnorB2E_YV7OAkU6Qr1u0Fn0TlVXkk8HZeZ7W2ZSJj2PuvFyN_kcxUlONVlVAav2XWyb_1jwTEsLi1juN2fZpe04-0DBlC7UhiWPr0sU28BvKPWCu_EglsCes-QteOaJS2v/s1600/toilet-door.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC470ptYoXn2sZ5VnorB2E_YV7OAkU6Qr1u0Fn0TlVXkk8HZeZ7W2ZSJj2PuvFyN_kcxUlONVlVAav2XWyb_1jwTEsLi1juN2fZpe04-0DBlC7UhiWPr0sU28BvKPWCu_EglsCes-QteOaJS2v/s400/toilet-door.jpg" width="400" height="256" data-original-width="1600" data-original-height="1022" /></a></div>
<p>What's nice about these sensors is that they're cheap, require no modification, and will run on a single AAA battery for many months. One thing to keep in mind is that it's important that the sensors send a signal every time they detect a state change in any direction, not just when they detect that the door/window has just been opened. Not all of the sensors on the market do that and sometimes it's not clear from the description.</p>
<p>The ESP8266 board I used was a Wemos D1 mini clone, here's what it looks like with the 433 MHz receiver board:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7hka9htOKc0wUz-3v_7LsbzXxHZleIaB2qgnWNQLDVPakF6TAsjdXsxOIanYNkRxJgIZLJ050XnM77O_8qKLg_D-CIDuxgIMZApZiENAmQA_pR1g860ajgUVTYDNlizZWSZxrWz3YGBabC6CR/s1600/toilet-esp8266.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7hka9htOKc0wUz-3v_7LsbzXxHZleIaB2qgnWNQLDVPakF6TAsjdXsxOIanYNkRxJgIZLJ050XnM77O_8qKLg_D-CIDuxgIMZApZiENAmQA_pR1g860ajgUVTYDNlizZWSZxrWz3YGBabC6CR/s400/toilet-esp8266.jpg" width="400" height="353" data-original-width="1600" data-original-height="1412" /></a></div>
<p>The rest is software, the ESP8266 is running an Arduino sketch and the web part uses Firebase. You can see the whole thing <a href="https://github.com/jfedor2/bathroom-occupancy-monitor">here</a>. The cloud function part isn't strictly necessary, the ESP8266 could write to the Firebase database directly, but it was much easier for me to do it this way.</p>
<p>Right now I'm only using the website to know if the bathroom is occupied, but it might be interesting to gather some statistics, such as the average time people spend in the bathroom or how likely it is to be occupied depending on time of day.</p>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-29021033951044372082020-02-15T15:03:00.001+01:002020-10-18T14:53:27.648+02:00Darkroom enlarger timer<p>I have recently started making traditional prints of my analog photos and it is a lot of fun in itself, but naturally I am also treating it as an excuse to play with some electronics. I have <a href="https://www.blogger.com/2020/02/darkroom-tray-timer.html">previously described</a> a simple timer I made for measuring how much time each print spends in the developer and fixer trays. Today I'd like to present my solution for the more important type of darkroom timer: the one that controls the exposure time on the enlarger. Here's what my setup looks like:</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSetqwKBJtYXfjRhDjHNaiIGpxgRbbwN_Hh82_2WVer88vod1Afx1LYr-vHGWya_lbmuM_z7GVApm19T7wfVqPx4gxrZy8pKrw4uVHHK-MGtuI0SMoF7tHFfWuK0ypSJ8Igq2cnKIlPdJto3aC/s1600/enlarger-timer.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1412" data-original-width="1600" height="353" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSetqwKBJtYXfjRhDjHNaiIGpxgRbbwN_Hh82_2WVer88vod1Afx1LYr-vHGWya_lbmuM_z7GVApm19T7wfVqPx4gxrZy8pKrw4uVHHK-MGtuI0SMoF7tHFfWuK0ypSJ8Igq2cnKIlPdJto3aC/s400/enlarger-timer.jpg" width="400" /></a></div>
<p>The enlarger lamp is connected through a reprogrammed <a href="https://www.itead.cc/smart-home/smart-socket.html">Sonoff S20</a> wifi smart plug. It runs a simple HTTP server written in <a href="https://micropython.org/">MicroPython</a>. It responds to three commands: "on", "off" and "expose". The last one takes a duration in milliseconds and switches the lamp on for that time.</p>
<p>The second component is a smartphone app written in <a href="https://flutter.dev/">Flutter</a>, so it should in theory run on both Android an iOS, but I have only tested on Android. It lets the user specify the exposure time, either directly or using a simple test strip mode. In test strip mode, exposures are made in such a way that if you cover a larger part of the paper before each exposure, the resulting exposure times of each part will be increasing in configured fractions of a stop.</p>
<p>Finally there's a footswitch, which is just a pedal converted into a USB keyboard using a <a href="http://digistump.com/products/1">Digispark</a> (which is an ATtiny85 board in the shape of a USB plug that can be programmed with Arduino). Whenever the pedal is pressed, the Digispark sends an "Enter" keystroke and the smartphone app reacts as if the "START" button was tapped and starts the next exposure.</p>
<p>The code for all three components is available <a href="https://github.com/jfedor2/darkroom-enlarger-timer">here</a>. To run the Python code on the smart plug, first it needs to be flashed with MicroPython firmware. The smartphone app is pretty basic right now and doesn't have fancy features like dry down compensation, saving dodge/burn programs or any split-grade automation. Another useful feature would be to have the safelight connected through another smart plug and turn it off when the enlarger lamp is turned on for focusing.</p>
<p>Oh, and even though the app's interface is all red, it's still probably not safe for photographic paper, so it's best to cover the phone's screen when the paper is out.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv8jW4rIJhtLfxPn-q7j3wj7M_F_c13frE5kZvsCcZGwxAGvHfuqzGtf9lptMbKV-U8iXGOxIun-ypHelsXYQH2pwhL-UYFCPumD89NDFEzQodQi56eMUbgaxG6z7RQQfBl0jaI0dEc43UGq9y/s1600/Screenshot+from+2020-02-15+14-43-55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv8jW4rIJhtLfxPn-q7j3wj7M_F_c13frE5kZvsCcZGwxAGvHfuqzGtf9lptMbKV-U8iXGOxIun-ypHelsXYQH2pwhL-UYFCPumD89NDFEzQodQi56eMUbgaxG6z7RQQfBl0jaI0dEc43UGq9y/s400/Screenshot+from+2020-02-15+14-43-55.png" width="187" height="400" data-original-width="403" data-original-height="864" /></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com2tag:blogger.com,1999:blog-5743520447405866726.post-38017239804739685732020-02-01T19:06:00.001+01:002020-10-18T14:53:40.582+02:00Darkroom tray timer<p>Two kinds of timers are used in a darkroom when making prints. One for controlling the exposure time on the enlarger and one for measuring the time the print spends in the developer, stop bath and fixer trays. Arguably the second kind is not as critical as the first, as any clock that displays seconds can be used for that purpose. Nevertheless I've made such a timer and I'm using it regularly when making prints. Here's what it looks like:</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkS23BXmSiROVXLnIbhAJcmu7n-9jPPqpIAVRs3UUfJbJzleAsSYysLjx-JcfiElBf3HpZJp4cv729bIS_IDt4rJvpWjpywe4ShdPIoPB9iRAcU7f2LN9PpV_1v37q8T7CIKANDqX3Z72YBUCZ/s1600/IMG_20200201_182215.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkS23BXmSiROVXLnIbhAJcmu7n-9jPPqpIAVRs3UUfJbJzleAsSYysLjx-JcfiElBf3HpZJp4cv729bIS_IDt4rJvpWjpywe4ShdPIoPB9iRAcU7f2LN9PpV_1v37q8T7CIKANDqX3Z72YBUCZ/s400/IMG_20200201_182215.jpg" width="400" /></a></div>
<p>As you can see it is operated with a foot switch and has no display. Instead it beeps when it's time to move the print to the next tray. Each press of the switch triggers the start of the next timer: first it measures 60 seconds for the developer, then 10 seconds for the stop bath, then 60 seconds for the fixer and finally 120 seconds for the wash (I'm using RC paper). After that it goes back to the first timer. A sequence of short beeps at the start confirms which timer we're currently on.</p>
<p>The case was designed in Fusion 360 and 3D printed in PETG. Inside there's an ATtiny85 chip, a piezo buzzer and a CR2032 battery. The code running on the ATtiny85 can be found <a href="https://github.com/jfedor2/darkroom-tray-timer">here</a> and a schematic of the connections is shown below. When the timer is not active it goes into deep sleep so the battery should hopefully last a long time. One thing to keep in mind when programming the ATtiny85 with Arduino is that not every core supports the <code>tone()</code> function, used to make sound with the buzzer. I'm using <a href="https://code.google.com/archive/p/arduino-tiny/">this one</a>.</p>
<p>Stay tuned for the next episode in which I show my solution for the enlarger timer.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2GDZ4fq8Sccbrwy6H8t6Nj8HNP_F-MipomFxLUK7C4bKsN8B7b-zCcNgj5T2LhwOLn2nnpyIDjlx3oAYK5QpL-DcU0afK8HZJgzaOKDt6B9GvVU2CwhCPVze1TJEUVCRIFwzP2VkgFj5jRexu/s1600/tray-timer-schematic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2GDZ4fq8Sccbrwy6H8t6Nj8HNP_F-MipomFxLUK7C4bKsN8B7b-zCcNgj5T2LhwOLn2nnpyIDjlx3oAYK5QpL-DcU0afK8HZJgzaOKDt6B9GvVU2CwhCPVze1TJEUVCRIFwzP2VkgFj5jRexu/s400/tray-timer-schematic.png" width="384" height="400" data-original-width="480" data-original-height="500" /></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-51128459065816275272019-06-13T22:54:00.002+02:002021-01-27T22:37:52.121+01:00Bluetooth trackball with all the electronics inside the ball<p><strong>Update (2021-01-27):</strong> I have made an improved version of this project, <a href="https://blog.jfedor.org/2021/01/bluetooth-trackball-mark-ii.html">see here for details</a>.
<p>For a while now I've been fascinated with the idea of making a trackball-type input device in which the ball itself would be the entire device. Unlike a regular trackball, where the ball is just a ball and registering its motion and communicating with the computer is done by external sensors and chips, here everything would live inside the ball. And now I have finally done it. Here's a video:</p>
<iframe width="480" height="270" src="https://www.youtube.com/embed/tXA6RVn0X1w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<p>And here's how I did it. For obvious reasons, the device couldn't use USB, it had to be Bluetooth. For registering the rotation of the ball, a combination of an accelerometer and a gyroscope seemed like a good way of ensuring smooth results. I ended up using the following components:</p>
<ul>
<li><a href="https://www.adafruit.com/product/1535">Adafruit Bluefruit EZ-Key</a></li>
<li>MPU-6050 accelerometer/gyro</li>
<li><a href="https://store.arduino.cc/arduino-micro">Arduino Micro</a> as the brains of the operation
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcKIDVorPMU6rIcYM2K7oA6UEIeeiS9luG3WRaUUDVeTTjeiN7HbfN1FxviSKmAyPJqYBiv_qZ8Fj2ENacDLohDmJsEaOvxnLEIIo_zVlVGX9-2jpTCC1CDxAAPtgBa6_hX24GO0W3sFtGz5z4/s1600/TRACKBOWL_bb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcKIDVorPMU6rIcYM2K7oA6UEIeeiS9luG3WRaUUDVeTTjeiN7HbfN1FxviSKmAyPJqYBiv_qZ8Fj2ENacDLohDmJsEaOvxnLEIIo_zVlVGX9-2jpTCC1CDxAAPtgBa6_hX24GO0W3sFtGz5z4/s400/TRACKBOWL_bb.png" width="400" height="288" data-original-width="1067" data-original-height="768" /></a></div>
<p>I designed the ball itself in Fusion 360 and then 3D printed it. It has a diameter of 10 centimeters and consists of three parts, two halves of the ball and an inside part that holds the electronics and the battery. The three parts screw together to form the ball. I also made a stand on which the ball can be rolled, but that's just to make it easier to use as a trackball, the stand is optional and the device works when held in the air as well.</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw4ritZ-O_BCruq3MiJH-V-AksNQhMjHAuTPuSdd9Wwul4XqsepZoK66atiP8FhEv9fhxEyhq7jhV73Ir2I9KjBi1Jvus4aO3Np4KHcfhn01zrPST8ppautjPdwduC7qB1kuq3RaC8NTwmM6j8/s1600/TRACKBOWL+test2.1+v32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw4ritZ-O_BCruq3MiJH-V-AksNQhMjHAuTPuSdd9Wwul4XqsepZoK66atiP8FhEv9fhxEyhq7jhV73Ir2I9KjBi1Jvus4aO3Np4KHcfhn01zrPST8ppautjPdwduC7qB1kuq3RaC8NTwmM6j8/s320/TRACKBOWL+test2.1+v32.png" width="320" height="270" data-original-width="1280" data-original-height="1080" /></a></div>
<p>Here's what it looks like inside (the MPU-6050 is under the battery):</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjduMc5UDITa2Zg5PCpUHg2f-qnT9XWPtp7H1bQQMXCeWau88Ar9fVq6KpRIzfjUO6FnFp3ugrB_SPBpV4zwcEHnK1JQiUaZXlz9qiv42rWnsgOaUwqC1BnakpVjHUW3dWRRphZv6YwXUKFtUQA/s1600/IMG_20190412_235037b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjduMc5UDITa2Zg5PCpUHg2f-qnT9XWPtp7H1bQQMXCeWau88Ar9fVq6KpRIzfjUO6FnFp3ugrB_SPBpV4zwcEHnK1JQiUaZXlz9qiv42rWnsgOaUwqC1BnakpVjHUW3dWRRphZv6YwXUKFtUQA/s320/IMG_20190412_235037b.jpg" width="320" height="274" data-original-width="1600" data-original-height="1369" /></a></div>
<p>For the software part, I was pleasantly surprised when I found out that the MPU-6050 chip can do the sensor fusion magic (combining the outputs of the accelerometer and the gyro) for us and just give us the 3D orientation in the form of a quaternion. What's left then for the Arduino to do is to read the current orientation, calculate the difference between the previous orientation and the current one, translate it to X and Y mouse cursor offsets and send the appropriate commands to the Bluetooth chip that will pass them on to the computer.</p>
<p><a href="https://github.com/jfedor2/trackbowl/blob/master/TRACKBOWL.ino">Here's the Arduino code.</a></p>
<p>You may wonder how the ball knows which direction the cursor should go when it's rotated in a certain direction. The answer is of course that it doesn't, so the initial mapping of the directions might not be correct. But it does know which way is up (because it has an accelerometer), so the directions can be calibrated by rotating the ball around the vertical axis.</p>
<p>While I personally consider this project a great success, there's always room for improvement. For example, the trackball would be a little more practical if it had the ability to click, not just to move the cursor. I explored the idea of detecting taps on the ball using the accelerometer, but found it hard to eliminate false positives. This area needs some additional work.</p>
<p>An obvious shortcoming of the current solution is that to switch the device on or off, I have to unscrew the two halves and connect or disconnect the battery. Ideally there would be some way of doing that without disassembling the ball, a magnetic switch of some sort or maybe the device could always be on and just go to sleep when it's not used for a while (like regular wireless mice do).</p>
<p>On a related note it would be really cool if we also didn't have to open the ball to change the battery. Seems like a good use case for wireless charging.</p>
<p>If I ever do a next version of this, I will probably try to use a different Bluetooth board, one that's not discontinued (and perhaps can do Bluetooth LE).</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjevUdRozUxOHNCrg2w2N5LNKBugaxPSQB_9qArUnidpoE0DimfdKTyTKa7WBeup8Pi9eqvjZYHau5kgiEf9lWZnP4xftLbE94qi6yzcr1hyphenhyphenWTBCn7P63_wfC8i1kxEw_pz4cM_FCUSgEUYNXU/s1600/IMG_20190412_233918b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjevUdRozUxOHNCrg2w2N5LNKBugaxPSQB_9qArUnidpoE0DimfdKTyTKa7WBeup8Pi9eqvjZYHau5kgiEf9lWZnP4xftLbE94qi6yzcr1hyphenhyphenWTBCn7P63_wfC8i1kxEw_pz4cM_FCUSgEUYNXU/s320/IMG_20190412_233918b.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com3tag:blogger.com,1999:blog-5743520447405866726.post-64538397869493972502019-06-11T22:55:00.001+02:002019-06-12T18:30:06.676+02:00Time tracking wifi cubeThere are many apps and websites for tracking time spent on projects and I'm sure they work well. But I like physical objects so I made a gadget - a cube that you can flip to a different face to indicate that you're now working on some project or task. Each face corresponds to a different project and one of the faces means you don't want to track time anymore. The idea is of course not original, there are similar commercial products available, but hey, this one's mine.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUjw-z0nHWrLRhIS3tkso6EIJXaP0wsC7Bp5fGk-k8jAz0M_24BLiasEeFq0o6XsiER-y2psaf1dn61COMjgEp2gRIPc7OX_AYZoykd-ensJeUHF21LWfTGyGDochQMWTDDfkjIc6crMJkJL57/s1600/IMG_20190521_193509.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUjw-z0nHWrLRhIS3tkso6EIJXaP0wsC7Bp5fGk-k8jAz0M_24BLiasEeFq0o6XsiER-y2psaf1dn61COMjgEp2gRIPc7OX_AYZoykd-ensJeUHF21LWfTGyGDochQMWTDDfkjIc6crMJkJL57/s320/IMG_20190521_193509.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div><br />
I had two design goals: first, I wanted the gadget to be standalone and not need a companion app on a phone or a computer. So it needs to have wifi and talk directly to the Internet. Second, I wanted the cube to last a long time on battery, at least a few months. So I had to learn a bit about how deep sleep modes work on microcontrollers.<br />
<br />
Here's a video that shows the cube in action. (The laptop is just there to show that time reporting works, as I said the cube talks to the Internet directly.)<br />
<br />
<iframe width="480" height="270" src="https://www.youtube.com/embed/WLYeqdwMPDU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br />
<br />
These are the parts that I used to make this happen:<br />
<br />
<ul><li>ESP8266 board (Wemos D1 mini) for wifi</li>
<li>MPU-6050 accelerometer to check which side the cube is flipped to</li>
<li>SW-18010P vibration sensor for detecting motion</li>
<li>ATtiny85 chip for watching the vibration sensor and waking up the wifi chip</li>
<li>MCP1826 voltage regulator with a shutdown pin that made it easy to switch the wifi chip on and off</li>
</ul><br />
The idea here is that most of the time the ESP8266 chip is off and the ATtiny85 chip is in deep sleep, using almost no power from the battery. It is set to wake up when the state of one of its pins changes - a pin connected to the vibration sensor. Then the ATtiny85 chip enables the voltage regulator, waking up the ESP8266 chip, which reads the orientation of the cube from the accelerometer and makes a HTTP request to report it to a time tracking service. When it's done it signals the ATtiny85 chip on another pin. The ATtiny85 then disables the voltage regulator and goes back to sleep, waiting for another interrupt on the vibration sensor pin. An LED indicates when the chips are awake.<br />
<br />
Here's a schematic of the connections. You may notice an extra button, I will explain its purpose in a moment.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi49ydL67Yu_xZlLZETCMJBwsRFI4SyTbm6C6e4iqhDq_Xbee9iYEgCbC1y4SApStb3zlTqSj2qpZGHUYhpQcklEwo6jqR-P0JdSlaTMqw2paiKlLge51COKesLbDhD_AZrbrGT4ApKg1bTxrHs/s1600/TimeCube_schematic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi49ydL67Yu_xZlLZETCMJBwsRFI4SyTbm6C6e4iqhDq_Xbee9iYEgCbC1y4SApStb3zlTqSj2qpZGHUYhpQcklEwo6jqR-P0JdSlaTMqw2paiKlLge51COKesLbDhD_AZrbrGT4ApKg1bTxrHs/s400/TimeCube_schematic.png" width="400" height="261" data-original-width="1550" data-original-height="1013" /></a></div><br />
And here's the code: the <a href="https://github.com/jfedor2/timecube/blob/master/TimeCube.ino">part running on the ATtiny85</a> is done in Arduino and the <a href="https://github.com/jfedor2/timecube/blob/master/main.py">ESP8266 part</a> in MicroPython.<br />
<br />
I used <a href="https://www.toggl.com/">Toggl</a> for tracking time, but any service with a reasonable API could be used, the cube just makes HTTP requests.<br />
<br />
Since the cube is woken up by motion, we have to consider what happens when you put it in a bag and take it with you. We don't want it to wake up constantly and deplete the battery. So here's how it works. The ESP8266 chip reads the accelerometer and waits for the readings to settle before making the HTTP request and signaling the ATtiny85 to go to sleep. So if the cube keeps moving, that signal never comes. And the ATtiny85 chip has a 30 second timeout. If it doesn't receive the signal before the timer runs out, it switches to "travel mode". Which means it goes back to sleep, but now it ignores the vibration sensor - it will only be woken up when the button is pressed. When it's pressed, it goes back to normal mode. That way we still get the long battery life, but we can take the cube with us.<br />
<br />
Currently pressing the button is not very convenient as the cube needs to be opened up to access it.<br />
<br />
Another improvement that comes to mind is making it work with multiple wifi networks. Currently it only remembers one, which makes it hard to use the same cube at, say, home and work.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj36GJNrnTgpAr6iaI_CcTFstwIEyEyPeOw0zA23XK4Q_a7UHOExcrA3VNdbjCpe6_7X4t_GQ9Vt3CdVAWRueSxbmwkVJfE299aHd1Kd4vJgNCINpMDfUlQjh1oRsZsp81JUhwtkhZwVXjIL5qH/s1600/IMG_20190521_193626.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj36GJNrnTgpAr6iaI_CcTFstwIEyEyPeOw0zA23XK4Q_a7UHOExcrA3VNdbjCpe6_7X4t_GQ9Vt3CdVAWRueSxbmwkVJfE299aHd1Kd4vJgNCINpMDfUlQjh1oRsZsp81JUhwtkhZwVXjIL5qH/s320/IMG_20190521_193626.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-43949486510630268022017-09-24T18:35:00.000+02:002018-04-21T15:23:17.930+02:00Google Assistant support for IKEA TRÅDFRI lights<strong>Update (2018-04-21):</strong> IKEA has rolled out official support for Google Assistant, so if you just want your lights to work with Google Home, you don't need any of this. If you're interested in the technical side, you may still find this post useful.<br />
<br />
Earlier this year I got some <a href="http://www.ikea.com/us/en/catalog/categories/departments/lighting/smart_lighting/">IKEA smart lights</a> from their TRÅDFRI line. They can be controlled by a remote and also through a smartphone app, if you have IKEA's <a href="http://www.ikea.com/us/en/catalog/products/00337813/">gateway</a>. Around the same time I also got a <a href="https://madeby.google.com/home/">Google Home</a> and naturally I wanted them all to work together. IKEA is planning to add official support for Google Assistant very soon, but in the meantime I rolled out my own. So while all this may be obsolete soon, I still wanted to publish it in the hope that it might be useful for someone (perhaps for adding Assistant support to some other smart lighting system without official support). Below I try to provide a step-by-step description of how I got it to work, but if you just want to see the code, <a href="https://github.com/jfedor2/ikea-tradfri-google-assistant">here it is</a>.<br />
<br />
Let's get started. We're going to need a computer on the same network as the IKEA gateway (or it must be able to reach it though some clever routing). I used a Raspberry Pi, but any computer running Linux will do. This computer needs to have its 443 port accessible from the Internet, so if it's behind a router, you need to configure port forwarding. We're also going to need a domain name that will point to our Linux box and a proper SSL/TLS certificate for that domain. I'm not going to go into details about these, but you can easily get a certificate for free at <a href="https://letsencrypt.org/">Let's Encrypt</a>. Below I'm using <i>home.example.com</i> as the domain name, obviously you should change it to your actual domain wherever it appears.<br />
<br />
The general architecture of the solution is as follows. We're going to create a <a href="https://developers.google.com/actions/smarthome/">Smart Home App</a> on Actions on Google and deploy it in testing mode. Then when we talk to the Google Assistant (on Google Home or a phone or a smartwatch), Google's cloud magic will make a call to our server, asking what lights are available or telling it to turn a certain light on or off. Then our app will talk to the IKEA gateway, which in turn talks to the light bulbs themselves. Using the Actions SDK instead of IFTTT means we will get to use more natural language commands without defining each phrase manually.<br />
<br />
Google's documentation likes to give all the examples in node.js, but the app can by anything as long as it speaks the proper API over HTTP. I wrote mine in Python using Django and deployed it using nginx and uwsgi, but any other way of <a href="https://docs.djangoproject.com/en/1.11/howto/deployment/">deploying a Django app</a> would also work.<br />
<br />
Let's get the code (below I assume we're running as the pi user, change to your actual user and group if they're different):<br />
<pre>sudo mkdir /var/www/<i>home.example.com</i>
sudo chown <i>pi</i>:<i>pi</i> /var/www/<i>home.example.com</i>
cd /var/www/<i>home.example.com</i>/
git clone https://github.com/jfedor2/ikea-tradfri-google-assistant.git .</pre>One more thing we're going to need is the <tt>coap-client</tt> tool, compiled with DTLS (encryption) support. It's what we're going to use to talk to the IKEA gateway. I'm going to borrow the instructions for compiling it from <a href="https://learn.pimoroni.com/tutorial/sandyj/controlling-ikea-tradfri-lights-from-your-pi">here</a>:<br />
<pre>sudo apt-get install build-essential autoconf automake libtool
git clone --recursive https://github.com/obgm/libcoap.git
cd libcoap
git checkout dtls
git submodule update --init --recursive
./autogen.sh
./configure --disable-documentation --disable-shared
make
sudo make install</pre>Once we have the <tt>coap-client</tt> tool installed, there's a one-time step that we need to perform to set up an identity that we'll use to authenticate to the IKEA gateway (in other words, a login and password). For that we will need to know the gateway's IP address on the local network and the security code that's printed on the bottom of the gateway. Also we need to come up with an identity (username) that we'll use. This can be anything, e.g. "foobar". With those in hand we run the following command (substituting the appropriate values):<br />
<pre>coap-client -m post -u Client_identity -k '<i>security code</i>' -e '{"9090":"<i>chosen username</i>"}' "coaps://<i>IP address of your IKEA gateway</i>:5684/15011/9063"</pre>The gateway should reply with a pre-shared key that we'll use for authentication. Write that down somewhere.<br />
<br />
Let's get back to our app and actually make it work. First, let's create a Python virtual environment for the app so that we can install the necessary modules locally:<br />
<pre>cd /var/www/<i>home.example.com</i>/
virtualenv .virtualenv
. .virtualenv/bin/activate
pip install -r requirements.txt</pre>Then we need to edit the Django settings file. You can either edit <tt>/var/www/<i>home.example.com</i>/tradfri/settings.py</tt> or leave that file unchanged and create a new file, <tt>/var/www/<i>home.example.com</i>/tradfri/local_settings.py</tt>, with just the settings that need changing locally. (That way it's easier to keep <tt>settings.py</tt> under version control.) You need to provide the following settings:<br />
<pre>SECRET_KEY = '<i>insert a long string of random characters here that you will keep private</i>'
ALLOWED_HOSTS = ['<i>home.example.com</i>']
COAP_CLIENT = '/usr/local/bin/coap-client' # or wherever you installed it
IKEA_IDENTITY = '<i>the username we chose above</i>'
IKEA_PRE_SHARED_KEY = '<i>the pre-shared key that the gateway provided</i>'
GATEWAY_ADDRESS = '<i>IP address of your IKEA gateway</i>'</pre>Depending on your local network configuration, it may also be useful to add the local IP address of your Linux computer to <tt>ALLOWED_HOSTS</tt> (if you're using port forwarding on the router, accessing the server through the proper domain name might not work from inside the network):<br />
<pre>ALLOWED_HOSTS = ['<i>home.example.com</i>', '<i>192.168.0.x</i>']</pre>Then, create the necessary tables in the database (run the following commands in the Python virtual environment created above - run the <tt>activate</tt> command before if you haven't already in this shell):<br />
<pre>./manage.py migrate</pre>And let's create a user that we will use for OAuth2 account linking:<br />
<pre>./manage.py createsuperuser</pre>Choose whatever username and password you want and remember them.<br />
<br />
In the extras directory, I provided example configuration files for nginx and uwsgi, <tt>home.example.com.conf</tt> and <tt>home.example.com.ini</tt>. Edit them with your specific settings and put them in <tt>/etc/nginx/sites-enabled/</tt> and <tt>/etc/uwsgi/apps-enabled/</tt>, respectively.<br />
<br />
After updating the configuration files, restart uwsgi and nginx (install them first if necessary):<br />
<pre>sudo apt-get install nginx uwsgi-plugin-python
sudo service uwsgi restart
sudo service nginx restart</pre>Whenever you change something in the Django app, you need to restart uwsgi.<br />
<br />
In the extras directory there's also an <tt>actions.json</tt> file, that we will use to tell Google where to look for our app. But first we need to create a project for it.<br />
<br />
Go to the <a href="https://console.actions.google.com/">Actions on Google console</a>. Click "Add/import project", choose a name and click "create project". In the "Add actions to your app" section, click on "Actions SDK". It will give you an example command that looks something like this:<br />
<pre>gactions update --action_package <i>PACKAGE_NAME</i> --project <i>smartlights-abc12</i></pre><i>smartlights-abc12</i> is your project ID, which you will need in a moment.<br />
<br />
Update the <tt>/var/www/<i>home.example.com</i>/extras/action.json</tt> file with your actual domain name, download the <a href="https://developers.google.com/actions/tools/gactions-cli">gactions command-line tool</a> and run it, substituting the actual project ID of course (you may have to provide a path to the tool if it's not in your PATH):<br />
<pre>gactions test --action_package /var/www/<i>home.example.com</i>/extras/action.json --project <i>smartlights-abc12</i></pre>This will put your app in testing mode and make it accessible in the Google Home app on your phone (you have to be using the same Google account). Google says an app only works in testing mode for 3 days, but I found that in reality it works indefinitely.<br />
<br />
In the Google Actions console you probably also need to provide some text and graphics for your app. It doesn't matter what you put there (no-one else is going to see it).<br />
<br />
Now all that is left is to set up OAuth2 for account linking. We need to configure it on both our app and the Actions on Google console. Go to <tt>https://<i>home.example.com</i>/oauth2/applications/</tt> or <tt>http://<i>192.168.0.x</i>/oauth2/applications/</tt> (substituting the correct address of course). Log in using the user and password you created with <tt>createsuperuser</tt>. Click "New Application". Put some name in (I used "google"), note the client ID and client secret (you're going to need them in a moment), choose "client type": "confidential", "authorization grant type": "authorization code" and put <tt>https://oauth-redirect.googleusercontent.com/r/<i>smartlights-abc12</i></tt> in "redirect uris" (substituting your project ID from above). Click "Save". Now go to the <a href="https://console.actions.google.com/">Actions on Google console</a> and in your project go to "Account linking". Choose "Authorization code" under "Grant type" as before. Under "Client information", paste the client ID and client secret that you saw in our app's web interface a moment ago. Then put <tt>https://<i>home.example.com</i>/oauth2/authorize/</tt> under "Authorization URL" and <tt>https://<i>home.example.com</i>/oauth2/token/</tt> under "Token URL". Click "save".<br />
<br />
We're almost done. Open the <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.chromecast.app">Google Home app</a> on your phone. Open the <a href="https://en.wikipedia.org/wiki/Hamburger_button">hamburger menu</a> and tap "Home control". Tap the plus icon in the bottom right corner. This should give you a long list of devices that are officially supported by the Google Assistant, but also our humble app should be there on the very top, with its name prefixed with "[test]". Tapping it should take you to a login form on our app. Login with the user and password you created with <tt>createsuperuser</tt> a few minutes ago and on the next screen confirm that you want to give Google access. (You may have to disable wifi on your phone and use the cellular network connection for this step if <tt>https://<i>home.example.com</i>/</tt> doesn't work from inside your local network.)<br />
<br />
Boom, that's it. You should get a list of your IKEA lights and be able to control them with Google Assistant.<br />
<br />
<strong>Update (2017-12-04):</strong> With version 1.2.42 of the IKEA gateway firmware, the authentication scheme changed. The code and this post have been updated accordingly.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy0P0vEpmcnDghPQrXJ4mqJVmCUqI-AwhIDBYPoCUIpfsMszpeUV3XvvPGxpHCSFT-CWqOz67CkrcOixqHsQrYB8luSYNVRkmBj1HU_f3yTYmTknmwdsAYwE8I4n-hzZrZs_a0pX4lvGOtmTQ0/s1600/DSCF5435b.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy0P0vEpmcnDghPQrXJ4mqJVmCUqI-AwhIDBYPoCUIpfsMszpeUV3XvvPGxpHCSFT-CWqOz67CkrcOixqHsQrYB8luSYNVRkmBj1HU_f3yTYmTknmwdsAYwE8I4n-hzZrZs_a0pX4lvGOtmTQ0/s480/DSCF5435b.JPG" width="480" height="320" data-original-width="1600" data-original-height="1067" /></a>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com5tag:blogger.com,1999:blog-5743520447405866726.post-10505696318624622732014-06-12T18:24:00.000+02:002014-06-12T18:27:09.870+02:00External notification light for your phoneAmong other interesting things, Android 4.3 introduced a proper way of <a href="http://developer.android.com/about/versions/jelly-bean.html#43-notification-access">accessing notifications</a> from an app. I used this API to make an external notification light for my phone:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZcea5FeDbk1xxs1BcRR4GYh5WywRHlorSqUxWxCQFCwiG4P5YcJLuNNE0VdxrQSwoQ0jWTDyxTuPX6Zz8AHFJ_TEYVYjkNcIZRsxKhL82xMgLDLfkNjVp5iGHiSIqrqg71ALZ8FO8hJO5BS4A/s1600/notification_light.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZcea5FeDbk1xxs1BcRR4GYh5WywRHlorSqUxWxCQFCwiG4P5YcJLuNNE0VdxrQSwoQ0jWTDyxTuPX6Zz8AHFJ_TEYVYjkNcIZRsxKhL82xMgLDLfkNjVp5iGHiSIqrqg71ALZ8FO8hJO5BS4A/s480/notification_light.jpg" /></a><br />
<br />
It uses Adafruit's <a href="http://www.adafruit.com/products/1500">Trinket</a>, a Bluetooth serial board from dx.com to talk to the phone and it's powered via USB. Here's a diagram of the connections:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiPNuVPpYghajC2IN50a6mivy1BP_Qai9tyKAfWGb0xlVS9TZkYiaSinvBFAuYtWd9j9hEOtwZkPQSTc2XZJT870FnrUqCuLndZHpa-5UoS7UPVHFhl6nRT-anniRXxbXH1nRK1SB8Q7tLPVJB/s1600/notification_light_bb.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiPNuVPpYghajC2IN50a6mivy1BP_Qai9tyKAfWGb0xlVS9TZkYiaSinvBFAuYtWd9j9hEOtwZkPQSTc2XZJT870FnrUqCuLndZHpa-5UoS7UPVHFhl6nRT-anniRXxbXH1nRK1SB8Q7tLPVJB/s480/notification_light_bb.png" /></a><br />
<br />
The Arduino sketch that's running on the Trinket is very simple, it listens on the serial line that's connected to the Bluetooth board and turns the LED on and off depending on what character is received. You can see the sketch <a href="http://www.jfedor.org/misc2/BluetoothNotification2.ino">here</a>. On Android side, the code is also pretty simple, there's an intent filter in the manifest to register a listener that gets called whenever a notification is posted or dismissed. In the listener we check what notifications are active and if they requested the notification light to be turned on (your phone might not even have a notification light, but the information is still there). Then we connect to the Trinket via Bluetooth and tell it to turn the LED on or off. You can see the code <a href="http://www.jfedor.org/misc2/NotificationRemote.zip">here</a>. There is no UI and the Bluetooth address is hardwired.<br />
<br />
There is no special permission in the manifest to let the app access notifications, instead you grant access via a checkbox in the security section of your phone's settings:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRl33WvAbf-kxxVWTHe5q6ledBoT_iB9umDZWWSCAeb5OMzX72P9A9UgjTMTLR8DddAyV2UkoidxZsMnzmaKDqscXna4aWYgdRKUhtnwnpbxSCDPSnQiBJTPeQtv52EbaAhDrMBUFayEc3Ebu3/s1600/Screenshot_2014-06-12-18-02-36.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRl33WvAbf-kxxVWTHe5q6ledBoT_iB9umDZWWSCAeb5OMzX72P9A9UgjTMTLR8DddAyV2UkoidxZsMnzmaKDqscXna4aWYgdRKUhtnwnpbxSCDPSnQiBJTPeQtv52EbaAhDrMBUFayEc3Ebu3/s480/Screenshot_2014-06-12-18-02-36.png" /></a><br />
<br />
As usual, there's room for improvement. For example if the phone fails to connect to the device via Bluetooth (because it's out of range or powered off), it should probably try again in some time. Also, we could have an RGB LED and send color and timing information, instead of just on/off state, to better replicate the behavior of the notification light.Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com2tag:blogger.com,1999:blog-5743520447405866726.post-16664281117740054232014-06-02T17:23:00.002+02:002023-04-20T22:20:38.710+02:00Morse code Bluetooth keyboardMy <a href="http://blog.jfedor.org/2013/10/morse-code-usb-keyboard.html">previous attempt</a> at a Morse code keyboard worked over USB and used a copper coin as a capacitive sensor. Since then I've acquired a real telegraph key and Adafruit's <a href="http://www.adafruit.com/products/1535">Bluefruit EZ-Key</a> board. With that and a <a href="http://www.adafruit.com/products/1500">Trinket</a> I made a Morse code Bluetooth keyboard. It works with any computer that has Bluetooth (also phones and tablets).<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhnCNF4V7M_KkZtugTv4maKXCgPrUtygp8TYI5ezL-YwHtwozAOGM7SMIpywFzNWagnBe7XefQVyy8nZE1hf1XnYGdXil98Reo-S5jdd2VO_IxsyPgncYFqokSYVPu-gLNsIPvYHI88QW0oegh/s1600/bluetooth_morse_keyboard.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhnCNF4V7M_KkZtugTv4maKXCgPrUtygp8TYI5ezL-YwHtwozAOGM7SMIpywFzNWagnBe7XefQVyy8nZE1hf1XnYGdXil98Reo-S5jdd2VO_IxsyPgncYFqokSYVPu-gLNsIPvYHI88QW0oegh/s480/bluetooth_morse_keyboard.jpg" /></a><br />
<br />
Here's what it looks like in action (as usual please excuse my lack of Morse code skills):<br />
<br />
<iframe width="480" height="320" src="//www.youtube.com/embed/nbToD-ydlBY?rel=0" frameborder="0" allowfullscreen></iframe><br />
<br />
Here's <a href="https://www.jfedor.org/misc2/MorseKeyBT.ino">the Arduino sketch</a> that's running on the Trinket. As before there's a buzzer for feedback and the transmission speed is fixed.<br />
<br />
If you're into Morse code, I continue to recommend <a href="https://play.google.com/store/apps/details?id=org.jfedor.morsecode">my Android application</a> that listens to Morse code using your smartphone's microphone and translates it to text.<br />
<br />
Here's a diagram of the connections:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibnrZGO7MJAuv-LXCFZAJjmGjzddSWoZuQVGrLHFRKCQXjLujss365DMByjRIIyetyTKPpPHCNi3k8bldUfPvMq4iq8E7xwxoIzeKUyjoyiL5VHWtg8dqSi9eoig2vHOcEncSE2RDjtc8Yt5OY/s1600/bluetooth_morse_keyboard_bb.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibnrZGO7MJAuv-LXCFZAJjmGjzddSWoZuQVGrLHFRKCQXjLujss365DMByjRIIyetyTKPpPHCNi3k8bldUfPvMq4iq8E7xwxoIzeKUyjoyiL5VHWtg8dqSi9eoig2vHOcEncSE2RDjtc8Yt5OY/s480/bluetooth_morse_keyboard_bb.png" /></a>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com1tag:blogger.com,1999:blog-5743520447405866726.post-58443319438067434862014-06-01T22:38:00.001+02:002020-10-18T14:54:20.190+02:00Bluetooth mouse from a Wii nunchuckI never had a Nintendo Wii, but I got a nunchuck controller to play with. It has a joystick, two buttons, an accelerometer for orientation sensing and the third-party ones are dirt cheap. It turns out that it's really easy to talk to them from an Arduino too, because they speak I2C and as you would expect the protocol is well documented on the Internet. I used Adafruit's <a href="http://www.adafruit.com/products/1500">Trinket</a>, <a href="http://www.adafruit.com/products/1535">Bluefruit EZ-Key</a> and <a href="http://www.adafruit.com/products/1570">a 100 mAh lipo battery</a> to turn the nunchuck into a Bluetooth mouse:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw4fO6Tb5rIemxQKmXV9pZ3q0njA3wSZh1m1kFi0ihebdpYDMcBcD5gRuZuSv0nQ5qBWdzjfBq6VyKc3u8VmR0lAQkLccYsbRuXJC698pGFbY3bF8_FP3yeJfDAUoUgAEoBaxwq5GRO8ys3QkB/s1600/IMG_20131128_042745.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw4fO6Tb5rIemxQKmXV9pZ3q0njA3wSZh1m1kFi0ihebdpYDMcBcD5gRuZuSv0nQ5qBWdzjfBq6VyKc3u8VmR0lAQkLccYsbRuXJC698pGFbY3bF8_FP3yeJfDAUoUgAEoBaxwq5GRO8ys3QkB/s480/IMG_20131128_042745.jpg" /></a><br />
<br />
Here's a diagram of the connections, pin 1 on the Trinket goes to the RX pin on the Bluefruit and pins 0 and 2 are used for the I2C communication with the nunchuck:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMvyT8kG9hD4rdlO7dRl6NafgPl_3FpubD4A3MCYXR7alxW0Cv0CtJYSPT6xYCtJhQSCUHQfqZ-ShtST_Pc_rlS2brZXP-mmpBdBk8lZDUAYYTIwzCGIYcMh9yLfNi7US1Db13tmZx4EUMJvFA/s1600/wii_nunchuck_mouse_bt_bb.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMvyT8kG9hD4rdlO7dRl6NafgPl_3FpubD4A3MCYXR7alxW0Cv0CtJYSPT6xYCtJhQSCUHQfqZ-ShtST_Pc_rlS2brZXP-mmpBdBk8lZDUAYYTIwzCGIYcMh9yLfNi7US1Db13tmZx4EUMJvFA/s480/wii_nunchuck_mouse_bt_bb.png" /></a><br />
<br />
On the software side, I used the WiiChuck class I found <a href="http://playground.arduino.cc/Main/WiiChuckClass">here</a>, but I modified it to use the <a href="https://github.com/adafruit/TinyWireM">TinyWireM library</a> for I2C. It is equivalent to the standard Arduino Wire library, but it runs on ATtiny chips like the one used by the Trinket. I also used <a href="http://gammon.com.au/Arduino/SendOnlySoftwareSerial.zip">this SendOnlySoftwareSerial library</a>. Here's <a href="http://www.jfedor.org/misc2/WiiMouseBT.zip">my sketch and the modified WiiChuck library</a>.<br />
<br />
I haven't found any clever use for the accelerometer inside the nunchuck yet, perhaps it could somehow be used for scrolling.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq9NUvv6yB1veF04H83x4VdU8_j6LiaN9ShtqbgkVE6et6w0Mx4isX86bMDsWhaJOuNAhqrEP0aOaWnS_YfeAZwZMSIB7xIIBO1rQ6qRf8ieegK2C4RtsyyoZM9pvMBG-eq9YR9OQQjlkfNiKm/s1600/IMG_20131128_042732.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq9NUvv6yB1veF04H83x4VdU8_j6LiaN9ShtqbgkVE6et6w0Mx4isX86bMDsWhaJOuNAhqrEP0aOaWnS_YfeAZwZMSIB7xIIBO1rQ6qRf8ieegK2C4RtsyyoZM9pvMBG-eq9YR9OQQjlkfNiKm/s480/IMG_20131128_042732.jpg" /></a>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com1tag:blogger.com,1999:blog-5743520447405866726.post-12979976742758648002014-06-01T14:51:00.000+02:002014-06-01T14:51:39.947+02:00Bluetooth emergency mute buttonSome time ago I made an <a href="http://blog.jfedor.org/2013/10/emergency-mute-button.html">emergency mute button</a> that connected over USB. Now with Adafruit's <a href="http://www.adafruit.com/products/1535">Bluefruit EZ-Key</a> I made a wireless version that works over Bluetooth. Look, no wires:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5Myid8ru5FgX_wbXtTpL5YSgk5StIMCcbtwQR3geL8iPGsoJGipicFux9aYjMygVjpjZyX-k1Av5_-rc_0pP5PedB6ZzwI5bE20zhVI27w6J_pFI2vIraZCIo3R1Lav8XZJ5pCit_fNZv6oK0/s1600/emergency_button.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5Myid8ru5FgX_wbXtTpL5YSgk5StIMCcbtwQR3geL8iPGsoJGipicFux9aYjMygVjpjZyX-k1Av5_-rc_0pP5PedB6ZzwI5bE20zhVI27w6J_pFI2vIraZCIo3R1Lav8XZJ5pCit_fNZv6oK0/s480/emergency_button.jpg" /></a><br />
<br />
In addition to the Bluefruit board, I used a <a href="http://www.adafruit.com/products/1500">Trinket</a> and a <a href="http://www.adafruit.com/products/1570">100 mAh lipo battery</a>. It all fit nicely inside the button:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYcGXtAj6mm0_ZjcXLYcfzkToPzByVQ5Dm_OZFME0B0KZbnOLSoH8HIEZu7rFu7FWQP8Qrg0JAhlbeMXQxLnM6u32JwyqYbEzVPj_io_jYCqYGOzS8GxiJvUh-qp4_bE1D4Z3iJ4fbjTiEKHQv/s1600/emergency_button_bt_inside.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYcGXtAj6mm0_ZjcXLYcfzkToPzByVQ5Dm_OZFME0B0KZbnOLSoH8HIEZu7rFu7FWQP8Qrg0JAhlbeMXQxLnM6u32JwyqYbEzVPj_io_jYCqYGOzS8GxiJvUh-qp4_bE1D4Z3iJ4fbjTiEKHQv/s480/emergency_button_bt_inside.jpg" /></a><br />
<br />
Here's a diagram of the connections:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0O_Ztnhx4OqlpxeW44wMc27swSnq10N1Q4t4DZYksqOQRfuQnQG7Yns1_XEImionfPPng-HDPNv0kRH65qvj9pskIREaklkhVg9cXCTohWn3L1Iq1kmFctU9DxzSY6WIbhi2DW6zkqse2rATA/s1600/emergency_mute_bt_bb.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0O_Ztnhx4OqlpxeW44wMc27swSnq10N1Q4t4DZYksqOQRfuQnQG7Yns1_XEImionfPPng-HDPNv0kRH65qvj9pskIREaklkhVg9cXCTohWn3L1Iq1kmFctU9DxzSY6WIbhi2DW6zkqse2rATA/s480/emergency_mute_bt_bb.png" /></a><br />
<br />
There's no on/off switch and to charge the battery I have to disassemble the whole thing, but hey, nobody's perfect. <a href="http://www.jfedor.org/misc2/MuteBT.ino">Here's the Arduino sketch</a> that's running on the Trinket, it simply sends the "mute" key code when it detects a change in the state of the button. I'm using <a href="http://gammon.com.au/Arduino/SendOnlySoftwareSerial.zip">this SendOnlySoftwareSerial library</a>, because I'm only sending data to the Bluefruit board.<br />
<br />
(You will notice that it still suffers from the synchronization problem that the USB version had - if you mute audio on your computer some other way than using the button, then pressing the button will actually unmute audio. It's because the button is stateful, but has no way of finding out what the actual state of audio on the computer is and there are no separate key codes for muting and unmuting.)Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-7919874905631701762014-05-31T20:43:00.000+02:002014-06-01T14:53:13.804+02:00DIY presentation clickerI think it is very cool that with a board like the Arduino it is easy to make your own USB input devices that speak the regular HID protocol and therefore work with any modern computer (and even some phones and tablets) without any additional software or drivers. For example I made this <a href="http://blog.jfedor.org/2013/10/emergency-mute-button.html">emergency mute button</a> that I still think is a very practical device. But making Bluetooth input devices used to be somewhat harder, until Adafruit released their <a href="http://www.adafruit.com/products/1535">Bluefruit EZ-Key</a>. Its purpose is making it easy to create devices that work as Bluetooth keyboards and mice. And in the simplest cases, it doesn't even require a separate microcontroller. I got one and to test it I made this presentation clicker:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjievriUNh7U3si3wlc8Id0DtnCs0Yf4lRs4XJx7blm0nUb3adEu_ybwZT4n5VTfGa-PIzHOgRw0QZRXbKxBwsrwkkAxxHW0XC7mSTu-F1vFhcMyDlz3nJsF8bz0JruWpb3KHszSkepkTOjNXue/s1600/IMG_20131125_013558.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjievriUNh7U3si3wlc8Id0DtnCs0Yf4lRs4XJx7blm0nUb3adEu_ybwZT4n5VTfGa-PIzHOgRw0QZRXbKxBwsrwkkAxxHW0XC7mSTu-F1vFhcMyDlz3nJsF8bz0JruWpb3KHszSkepkTOjNXue/s480/IMG_20131125_013558.jpg" /></a><br />
<br />
It has two buttons that are connected directly to Bluefruit's pins 2 and 3 that correspond to left/right arrow keys by default:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir-VmjyQ_xU8d-OrLzzc9sKuqB4ysNIE7oOiKLoNQ-HehbpM1_NkqjlqbothoPformc_wtqvvh-saqy8YazdLo92WuN2s2eQAgRjhuGZjEy0rmRHnIqfD73jfq3WvLfBdTOlETsvJUE9VSpk4r/s1600/presentation_clicker_bb.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir-VmjyQ_xU8d-OrLzzc9sKuqB4ysNIE7oOiKLoNQ-HehbpM1_NkqjlqbothoPformc_wtqvvh-saqy8YazdLo92WuN2s2eQAgRjhuGZjEy0rmRHnIqfD73jfq3WvLfBdTOlETsvJUE9VSpk4r/s480/presentation_clicker_bb.png" /></a><br />
<br />
And then it's enough to provide power (I used a coin cell battery) and pair it with your computer. The form factor is reasonable so I could even imagine using it in real life:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPsoUwAayzmP5xwx7dvp0_7HizhB1s4_o6HQKx7UyFB7Yb-hBFZW3hTJRxvZBNbk5WADbJC00KnvriZjsExJOw7Ex7iSe8Oz_YKSqxz495hjxo9bWqqZtuGAwMu2TGoRi6IOK860q2NITaGFik/s1600/IMG_20131125_014517.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPsoUwAayzmP5xwx7dvp0_7HizhB1s4_o6HQKx7UyFB7Yb-hBFZW3hTJRxvZBNbk5WADbJC00KnvriZjsExJOw7Ex7iSe8Oz_YKSqxz495hjxo9bWqqZtuGAwMu2TGoRi6IOK860q2NITaGFik/s480/IMG_20131125_014517.jpg" /></a>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com0tag:blogger.com,1999:blog-5743520447405866726.post-88868873790789818842014-05-31T19:29:00.000+02:002014-06-01T14:53:26.071+02:00Bluetooth thermometerSome time ago <a href="http://blog.jfedor.org/2012/10/fridge-temperature-monitoring-with.html">I measured the temperature inside my fridge</a> with a Raspberry Pi and a TMP36 sensor. That was cool, but obviously you don't need an entire computer running Linux just to report temperature. So I made a wireless thermometer using <a href="http://www.adafruit.com/products/1500">Adafruit's Trinket</a>, a DHT22 temperature/humidity sensor and a cheap Bluetooth serial module from dx.com. Here's what it looks like:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTgLnQCHdWPbLFad03o29IYOhKXoVc7DVrhfui0M86CuFM3bzIEBLSnlOk_n8sJLrxVyMeRqjAEf43OIfVA0FqcfeTaItrrHsf5DRViE1X0xXW1FwG_ljuJ9wzfTuWQB4r4sXnlNsde3fEeGxD/s1600/IMG_20131122_010207.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTgLnQCHdWPbLFad03o29IYOhKXoVc7DVrhfui0M86CuFM3bzIEBLSnlOk_n8sJLrxVyMeRqjAEf43OIfVA0FqcfeTaItrrHsf5DRViE1X0xXW1FwG_ljuJ9wzfTuWQB4r4sXnlNsde3fEeGxD/s480/IMG_20131122_010207.jpg" /></a><br />
<br />
And here's a diagram:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4ZQ95RlJpGOuvgvaNhyphenhyphen2g0mvoX_VftP8xhIT5jrbx5vJjCmaQzDp1998tUz8T0rq-bZMDlDPVLfoZCGtBQW0NoRJzIVf_YdUyjcICAn-uHlG4qqyTFQR8gEGELGwLhQiC3vVMjsLHckLKeU2P/s1600/bluetooth_thermometer_bb_1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4ZQ95RlJpGOuvgvaNhyphenhyphen2g0mvoX_VftP8xhIT5jrbx5vJjCmaQzDp1998tUz8T0rq-bZMDlDPVLfoZCGtBQW0NoRJzIVf_YdUyjcICAn-uHlG4qqyTFQR8gEGELGwLhQiC3vVMjsLHckLKeU2P/s480/bluetooth_thermometer_bb_1.png" /></a><br />
<br />
The connections are pretty straightforward, I used three AA batteries for power, which was fine for the 3.3V Trinket and the Bluetooth module. I connected the DHT22 sensor to the regulated 3.3V output on the Trinket. I only connected the RX pin on the Bluetooth module, because I was only going to be sending data. The DHT22 sensor also has one data pin and there's a 10K pull up resistor between the data pin and VCC.<br />
<br />
As far as software goes, I used <a href="https://github.com/nethoncho/Arduino-DHT22">this library</a> to talk to the DHT22 sensor, because the one from Adafruit that I used previously with a real Arduino didn't want to work on a Trinket for some reason. I also used <a href="http://gammon.com.au/Arduino/SendOnlySoftwareSerial.zip">this SendOnlySoftwareSerial library</a> because I was only sending data and with the regular SoftwareSerial library the sketch wouldn't fit in Trinket's limited memory. You can the sketch I used <a href="http://www.jfedor.org/misc2/DHT_Trinket2.ino">here</a>, it's a simple modification of the example sketch that comes with the DHT22 library.<br />
<br />
To read the temperature from this thermometer, you need a device (phone, tablet, computer) with Bluetooth and a terminal application. It prints the temperature and humidity every two seconds:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPpynMLLLsTm8Tc-beuA30hjRRy_XyhI5BYZlDkVg5g2zSbwNzllBr0MjDdLj0d-qil5wGS518W8qVCvZqlbJqSQxZoTkH26SRrJ1byGAC3WAelzxiVgQin0C-oEM7GQgkUTAynsTBw2OXLjJE/s1600/IMG_20131122_005722.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPpynMLLLsTm8Tc-beuA30hjRRy_XyhI5BYZlDkVg5g2zSbwNzllBr0MjDdLj0d-qil5wGS518W8qVCvZqlbJqSQxZoTkH26SRrJ1byGAC3WAelzxiVgQin0C-oEM7GQgkUTAynsTBw2OXLjJE/s480/IMG_20131122_005722.jpg" /></a>Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com2tag:blogger.com,1999:blog-5743520447405866726.post-30776808056608842122014-05-30T22:15:00.000+02:002019-07-20T23:05:46.102+02:00Bitcoin price tickerYou can get some cool stuff for cheap on <a href="http://www.dx.com/">dx.com</a>. For example <a href="http://www.dx.com/s/tm1638">this TM1638 display board</a> costs around $8 and has eight 7-segment digits, eight two-color LEDs and eight buttons. I connected it to a Raspberry Pi and made a Bitcoin price ticker:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjLCWx9z2J2TiAdo0Zh7oWyIipi3yTqOM8Z4AI_sqh3dZJKILaoy8GmBE1Y-LDMDtfsx2i5cVgapDmv4Mdc_Y2gD9AY-o63c5nPfjP2RSJkNh0Pws3sp-5SCd_8F0wkfh5dt8cJvvnE4mqvVs5/s1600/IMG_20140530_212210.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjLCWx9z2J2TiAdo0Zh7oWyIipi3yTqOM8Z4AI_sqh3dZJKILaoy8GmBE1Y-LDMDtfsx2i5cVgapDmv4Mdc_Y2gD9AY-o63c5nPfjP2RSJkNh0Pws3sp-5SCd_8F0wkfh5dt8cJvvnE4mqvVs5/s480/IMG_20140530_212210.jpg" /></a><br />
<br />
Even though I didn't get any documentation with the board, the protocol it uses is well known on the Internet, I found <a href="https://code.google.com/p/tm1638-library/">this Arduino library</a> and ported the parts I needed to Python to run on the Pi. You need three GPIO pins on the Pi to connect to DIO, CLK and STB0 pins on the board. You also need to connect the VCC pin on the board to the 5V pin on the Pi and GND to any of the grounds.<br />
<br />
Getting a price to display is easy, Bitcoin exchanges usually provide this data via a JSON service. You can see my code <a href="http://www.jfedor.org/misc2/btc-ticker.zip">here</a>.<br />
<br />
Like I mentioned before, the display board also has buttons, so it would be nice to extend this to display prices from multiple exchanges, using the buttons to select which price you want to see.Jacek Fedoryńskihttp://www.blogger.com/profile/11480276832274345787noreply@blogger.com