tag:blogger.com,1999:blog-39676132509752759252024-03-29T19:03:40.295+08:00ProjectProtoPrototype Projects - experiments on theoretical electronics/electrical designs and actual prototype circuits.'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.comBlogger84125tag:blogger.com,1999:blog-3967613250975275925.post-80241919085671167582022-12-06T12:38:00.000+08:002022-12-06T12:38:47.392+08:00D.I.Y. Electronic Chess Board<p><span class="style-scope yt-formatted-string" dir="auto">3D-printed Chess Board with Piece Recognition and Connection with Lichess<br />main controller: ESP32-WROOM w/ OLED display<br />RFID reader: mini RC522 modules<br />piece RFID: NTAG213 stickers</span></p><p><span class="style-scope yt-formatted-string" dir="auto"> diagram:<br /> <br /></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjdvtZnzXg2kjacEW0ejThZ4kF7PvJn1Au41BY-33fAFmk_xDq6wp3whU5hQBSiy5Yh_nkPmiUbFujEa6DdYGN5YL2bAO2GhruDQKQPYZ9XHlBN2QaAMtv8yql9BaNPn0M2iDXU6vVDwICdLMZOHPE15saiipfnVYRtAeNVHYrqUZlqHlK0NeYa6JAFg/s700/diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="700" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjdvtZnzXg2kjacEW0ejThZ4kF7PvJn1Au41BY-33fAFmk_xDq6wp3whU5hQBSiy5Yh_nkPmiUbFujEa6DdYGN5YL2bAO2GhruDQKQPYZ9XHlBN2QaAMtv8yql9BaNPn0M2iDXU6vVDwICdLMZOHPE15saiipfnVYRtAeNVHYrqUZlqHlK0NeYa6JAFg/s320/diagram.png" width="320" /></a></div><br /><p></p><p>part 1: Assembly<br /> <br /></p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/Ktdif_EhXoU" width="320" youtube-src-id="Ktdif_EhXoU"></iframe></div><p></p><p>part 2: Demo<br /><br /></p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/-xZdgco_sMA" width="320" youtube-src-id="-xZdgco_sMA"></iframe></div><br />'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com0tag:blogger.com,1999:blog-3967613250975275925.post-11144542408989998252022-07-10T21:11:00.000+08:002022-07-10T21:11:31.947+08:003D-Printed WALL-E Replica<p>3D-printed WALL-E replica - Wi-Fi controlled using ESP32, with OLED display and audio output.</p>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="BLOG_video_class" height="225" src="https://www.youtube.com/embed/5Xwboeo12-M" width="400" youtube-src-id="5Xwboeo12-M"></iframe>
</div>
<br />
<p>main controller: <a href="https://randomnerdtutorials.com/getting-started-with-esp32/" target="_blank">ESP32 DEVKIT</a> (with local web server)<br />motors: 2x 37GB520 (wheels/tracks - driven using TB6612FNG) and 7x MG90S servos<br />other accessories: 1x OLED display, 1x microSD interface, 1x audio-amplifier<br /><br /></p><p>credits:<br />original 3D design: <a href="http://thingiverse.com/thing:3703555" target="_blank">thingiverse.com/thing:3703555</a><br /></p>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com0tag:blogger.com,1999:blog-3967613250975275925.post-83925631471938467212022-06-18T19:01:00.003+08:002022-06-18T19:13:38.476+08:00DIY Mini Chess Clock<p>DIY rechargeable mini-chess-clock using <a href="https://www.sparkfun.com/products/13664" rel="nofollow" target="_blank">SAMD21 mini board</a> and 0.91" 128x32 OLED display.<br /></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3s8HeneifNf6axRuF2HZLfR123pU_PkrAS-FpuCZ8-2W5LiQBoD3p4PaZyWvLQSD-5jrk0qam6zlOoxivsL3iPsOed9-i0nnIL2EvEg2ZAx2hR4LFsJpbkjQeQN1gqErNJrdiDPWS1S1YAd2N0StVuAW4HMBlSZXDt8-lTSQqVtLob-cYZo3ydgmQ5Q/s4624/IMG_20220609_213247.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3472" data-original-width="4624" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3s8HeneifNf6axRuF2HZLfR123pU_PkrAS-FpuCZ8-2W5LiQBoD3p4PaZyWvLQSD-5jrk0qam6zlOoxivsL3iPsOed9-i0nnIL2EvEg2ZAx2hR4LFsJpbkjQeQN1gqErNJrdiDPWS1S1YAd2N0StVuAW4HMBlSZXDt8-lTSQqVtLob-cYZo3ydgmQ5Q/s320/IMG_20220609_213247.jpg" width="320" /></a></div><br /> demo:<p></p><p></p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/9xsxcWRFcvc" width="320" youtube-src-id="9xsxcWRFcvc"></iframe></div><br /> Arduino code: <a href="https://gist.github.com/julznc/48da0ecbb0afa2e1ade0389dc1e09ca6" target="_blank">chess-clock.ino</a><br /><p></p>
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidCzPjPXfTcOKvySWOl2GTns3JyJlqfEyxfvXISE3mRxGiqcXSfKryZk8dlPbuiQDVxS4AiEZ8EJD3kRKejyEg24CqmG4pCvQa30rHIlZ7j65b7E3IJZqi8lFdatY-JIAyy0fVExLezlrUvZgyIyF5Jh2ZwaXfPIfiGhsMZOuJD6o2KC7ptfZ_gcKWQA/s4624/IMG_20220605_184214.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3472" data-original-width="4624" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidCzPjPXfTcOKvySWOl2GTns3JyJlqfEyxfvXISE3mRxGiqcXSfKryZk8dlPbuiQDVxS4AiEZ8EJD3kRKejyEg24CqmG4pCvQa30rHIlZ7j65b7E3IJZqi8lFdatY-JIAyy0fVExLezlrUvZgyIyF5Jh2ZwaXfPIfiGhsMZOuJD6o2KC7ptfZ_gcKWQA/s320/IMG_20220605_184214.jpg" width="320" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghRDt24aJONXXRMS09RqJTUhY_qfPKpgsiFcorxuwkt53QWg5dHzQMKYlOeBexb9bvKnjbvyHYOAj2B3gHtOut16hd48Z1Ind9gbziROaYj0IcTHCnpqt5yYbr3eiSTJ0dpSXO0SiTW64ih-nay9ZZ1zz7SIVubp5UeiXu7PZ7cyFQ2G_-wvPqrJKYLA/s4624/IMG_20220609_191601.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3472" data-original-width="4624" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghRDt24aJONXXRMS09RqJTUhY_qfPKpgsiFcorxuwkt53QWg5dHzQMKYlOeBexb9bvKnjbvyHYOAj2B3gHtOut16hd48Z1Ind9gbziROaYj0IcTHCnpqt5yYbr3eiSTJ0dpSXO0SiTW64ih-nay9ZZ1zz7SIVubp5UeiXu7PZ7cyFQ2G_-wvPqrJKYLA/s320/IMG_20220609_191601.jpg" width="320" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQLc1ScRb5earFMfRd-OPCY-Jz6XSl75ApvC_yymS1xt98TCHNsQKMvMu1lJL6wGTe3avfyobTQ-N-WeYXbMP0ILn3P2uLJ6CJL6IDm-f1NLJH3p2ugZcoG1eWIvss5t2faBsswnm_pOr0B-xt1N7CskPLEpAXZLpkZpkf-7RRX5odcYYpa4r8djHhtg/s4624/IMG_20220609_220446.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3472" data-original-width="4624" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQLc1ScRb5earFMfRd-OPCY-Jz6XSl75ApvC_yymS1xt98TCHNsQKMvMu1lJL6wGTe3avfyobTQ-N-WeYXbMP0ILn3P2uLJ6CJL6IDm-f1NLJH3p2ugZcoG1eWIvss5t2faBsswnm_pOr0B-xt1N7CskPLEpAXZLpkZpkf-7RRX5odcYYpa4r8djHhtg/s320/IMG_20220609_220446.jpg" width="320" /></a></div><br />'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com0tag:blogger.com,1999:blog-3967613250975275925.post-14929974195210744292022-05-02T17:28:00.009+08:002022-05-05T09:55:48.970+08:00Cheap CMSIS-DAP/DAPLink Debugger+Serial Port Module<p>Cheap CMSIS-DAP/DAPLink SWD module based on <a href="http://ns32mcu.com/" rel="nofollow" target="_blank">NS32</a>F103CBT6 (an STM32-clone?). It has both a debugger and a serial/UART port on a single USB device just like the <a href="https://www.segger.com/products/debug-probes/j-link/models/j-link-ob/" rel="nofollow" target="_blank">J-Link OB v2</a> debugger (based on STM32F072) - better than those ST-Link debugger clones.<br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuwKZBT8ssxVGwngTrJQFmuuqsbuJH2RxLCfrvKyRJ9XZibLQoqFhmYyVWbontP-6dhBD5jxNwlC-hA2FumNxJ9s9QwiHBZ4584Tol_jv1tV5pdmEar-b8w4FeH6yiBp2IBwvQ-tV0f7I_jyUDlMnKdfLRnEeDhg1te3OILkkN7eA5mid6ZAsobLNaOw/s1024/ns32f103cbt6.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="768" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuwKZBT8ssxVGwngTrJQFmuuqsbuJH2RxLCfrvKyRJ9XZibLQoqFhmYyVWbontP-6dhBD5jxNwlC-hA2FumNxJ9s9QwiHBZ4584Tol_jv1tV5pdmEar-b8w4FeH6yiBp2IBwvQ-tV0f7I_jyUDlMnKdfLRnEeDhg1te3OILkkN7eA5mid6ZAsobLNaOw/s320/ns32f103cbt6.jpg" width="360" /></a></div><p>
</p><p><span style="font-size: x-small;">MCU interface:<br /></span></p><ul style="text-align: left;"><li><span style="font-size: x-small;">SWD (with pull-up resistors to 3V3)</span></li><ul><li><span style="font-size: x-small;">PB10 - CLK</span></li><li><span style="font-size: x-small;">PB11 - DAT</span></li></ul><li><span style="font-size: x-small;">CDC-UART (UART1)<br /></span></li><ul><li><span style="font-size: x-small;">PA9 - TXD</span></li><li><span style="font-size: x-small;">PA10 - RXD</span></li></ul><li><span style="font-size: x-small;">LEDs (active high)</span></li><ul><li><span style="font-size: x-small;">PA2 - running status<br /></span></li><li><span style="font-size: x-small;">PA3 - connected status<br /></span></li></ul><li><span style="font-size: x-small;">USB:</span></li><ul><li><span style="font-size: x-small;">PA11</span></li><li><span style="font-size: x-small;">PA12 (with fixed pull-up resistor)<br /></span></li></ul></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxvcLI1PPxRh3QgxJBA05EBjdtE9Ixd8Q6vJqkUDAuBWOo8lhjt8zFh672KyMcrNOSphrrO2R96nreAhy_etygJjuBnul39E7nvp3fEWSP4ue_syh-RBo9zOoz7amZHbAPlx3Ca4n2wqavpzIw7IxmigAllL3BjsdiOUdxWrZikPHF8EuV7ogV06CHAQ/s1024/daplink-pins.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="768" data-original-width="1024" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxvcLI1PPxRh3QgxJBA05EBjdtE9Ixd8Q6vJqkUDAuBWOo8lhjt8zFh672KyMcrNOSphrrO2R96nreAhy_etygJjuBnul39E7nvp3fEWSP4ue_syh-RBo9zOoz7amZHbAPlx3Ca4n2wqavpzIw7IxmigAllL3BjsdiOUdxWrZikPHF8EuV7ogV06CHAQ/s320/daplink-pins.jpg" width="400" /></a></div>
<br /> <p></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7hqCBJR8lqYVwlau_YTgvrnbRTB-tR5qw-9EECMmM8GMgU1vRcfTD-8255h2c9-BGlnLE6yduxO6OS1QZT2Ok5PxixWBvYPqY_mXshoJ5JghVaJfsq7fVLj4KDh6wbFDK1OVs8IG6KV3aX_AYGFTxaD-6k_96RiN3BZ8XzYU17RtctwmAtwLoRMDCBw/s1024/daplink-back.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="768" data-original-width="1024" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7hqCBJR8lqYVwlau_YTgvrnbRTB-tR5qw-9EECMmM8GMgU1vRcfTD-8255h2c9-BGlnLE6yduxO6OS1QZT2Ok5PxixWBvYPqY_mXshoJ5JghVaJfsq7fVLj4KDh6wbFDK1OVs8IG6KV3aX_AYGFTxaD-6k_96RiN3BZ8XzYU17RtctwmAtwLoRMDCBw/s320/daplink-back.jpg" width="400" /></a></div>
<br /><p><a href="https://gist.github.com/julznc/345d7c70d1a2c321affab156c6965164">Firmwares</a>:<br /><i><span style="font-size: x-small;">(*should work also on chips with smaller ROM STM32F103C8 (like the BluePill C8)</span></i><br /></p>
<ul style="text-align: left;">
<li>original: <a href="https://gist.githubusercontent.com/julznc/345d7c70d1a2c321affab156c6965164/raw/1e77beaba535436b3cddd0bf1a788b9e741ffcc3/CMSIS_DAP-NS32F103CB-original-fw.hex" target="_blank">CMSIS_DAP-NS32F103CB-original-fw.hex</a></li>
<li>modified: <a href="https://gist.githubusercontent.com/julznc/345d7c70d1a2c321affab156c6965164/raw/1e77beaba535436b3cddd0bf1a788b9e741ffcc3/DAPLink-CMSIS_DAP-32f103-SWD_PB10PB11-CDC_PA9PA10-LED_PA2PA3.hex" target="_blank">DAPLink-CMSIS_DAP-32f103-SWD_PB10PB11-CDC_PA9PA10-LED_PA2PA3.hex</a> </li>
</ul><p>
</p><p>Tested only on Ubuntu host.<br />sample kernel logs if using original FW:<br /></p><blockquote><span style="background-color: #eeeeee;"><span style="font-size: x-small;"><span style="font-family: courier;">usb 1-1: new full-speed USB device number 44 using xhci_hcd<br />usb 1-1: New USB device found, idVendor=c251, idProduct=f001, bcdDevice= 1.00<br />usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3<br />usb 1-1: Product: CMSIS_DAP<br />usb 1-1: Manufacturer: CMSIS-DAP by ARM<br />usb 1-1: SerialNumber: 202108120001<br />cdc_acm 1-1:1.0: ttyACM0: USB ACM device<br />hid-generic 0003:C251:F001.0015: hiddev0,hidraw2: USB HID v1.00 Device [CMSIS-DAP by ARM CMSIS_DAP] on usb-0000:00:14.0-1/input2</span></span></span></blockquote><p></p><p>Sample kernel logs if using the modified FW:<br /></p><blockquote><span style="background-color: #eeeeee;"><span style="font-size: x-small;"><span style="font-family: courier;">usb 1-1: new full-speed USB device number 52 using xhci_hcd<br />usb 1-1: device descriptor read/64, error -71<br />usb 1-1: new full-speed USB device number 53 using xhci_hcd<br />usb 1-1: New USB device found, idVendor=0d28, idProduct=0204, bcdDevice= 1.00<br />usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3<br />usb 1-1: Product: DAPLink CMSIS-DAP<br />usb 1-1: Manufacturer: ARM<br />usb 1-1: SerialNumber: 20220218979699080605210b3030153632303030<br />cdc_acm 1-1:1.0: ttyACM0: USB ACM device<br />usbcore: registered new interface driver cdc_acm<br />usbhid 1-1:1.2: couldn't find an input interrupt endpoint<br />usbcore: registered new interface driver usbhid<br />usbhid: USB HID core driver<br /><br /></span></span></span></blockquote><p>Sample openocd configuration:<br /><span style="font-size: x-small;"></span></p><blockquote><span style="font-size: x-small;"><span style="background-color: #eeeeee;"><span style="font-family: courier;">source [find interface/cmsis-dap.cfg]<br />transport select swd<br />source [find target/stm32f4x.cfg]<br />adapter speed 4000<br />init<br />targets<br />reset halt</span></span></span></blockquote>If using the original FW, need to add these on the configuration:<br /><blockquote><span style="background-color: #eeeeee;"><span style="font-size: x-small;"><span style="font-family: courier;">cmsis_dap_vid_pid 0xc251 0xf001<br />cmsis_dap_backend hid</span></span></span></blockquote>
<p></p><p>Not tested:<br /></p>
<ul style="text-align: left;">
<li>UDisk drag-n-drop <i><span style="font-size: x-small;">(looks like not working)</span></i></li>
<li>WebUSB <br /></li>
</ul><p> </p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmRBInWWZt9yP-RVJ8kUgKfd-07YcA5wZmsjAnYtEg8cglZAObuWQu6Vt9ZHn6m6zxbFxRfIdZCrc9yWYwmkdc4vAwIcB3usjqxxFq1D1XhEyPyie5EaYE1hj6w6r61htGQaWMBuT_aBWGaiO0KjqriX2bUUfIysMmA5e2EGvMK5T8knMf-UYxk_QlBQ/s2048/modules.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1536" data-original-width="2048" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmRBInWWZt9yP-RVJ8kUgKfd-07YcA5wZmsjAnYtEg8cglZAObuWQu6Vt9ZHn6m6zxbFxRfIdZCrc9yWYwmkdc4vAwIcB3usjqxxFq1D1XhEyPyie5EaYE1hj6w6r61htGQaWMBuT_aBWGaiO0KjqriX2bUUfIysMmA5e2EGvMK5T8knMf-UYxk_QlBQ/s320/modules.jpg" width="400" /></a></div>
size comparison (from left to right) :
<ol>
<li>Blue Pill STM32F103C8</li>
<li><a href="https://github.com/kaidegit/CMSIS-DAPbyWCH" rel="nofollow" target="_blank">WCH-Link</a> (based on 8051 mcu) - cheaper<br /></li>
<li><a href="https://bit.ly/3vydCbD" target="_blank">NS32F103CB</a> module</li>
<li>J-Link OB v2 clone (STM32F072CB)</li>
</ol><br />
<p> </p><p>Reference: <br /></p><ul style="text-align: left;"><li>Official ARM DAPLink source code: <a href="https://github.com/ARMmbed/DAPLink">https://github.com/ARMmbed/DAPLink</a></li></ul><p> </p>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com0tag:blogger.com,1999:blog-3967613250975275925.post-58101524258411342732020-10-05T10:25:00.003+08:002020-10-05T10:25:20.767+08:00STM32 LED Color Matching For KidsFun activity for kids with simple LED circuit! The LEDs will light up when the corresponding connectors of the same color are matching.
<iframe width="420" height="236" src="https://www.youtube.com/embed/rZa0OPlEVOE?start=125" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZAgOnc75f7k6civ4ODmZUTYKpZlHWIIMS0QPIsk2saafaUxg9g3ENCd-quhtIB9OaZ18rkVKji_llssdg6FiZucvJpiPf1h0qpR-merU0It0dWCjDJmD4I6uE2LObWiuAvClJbHFeEBrz/s1920/stm32-led-color-match.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="1080" data-original-width="1920" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZAgOnc75f7k6civ4ODmZUTYKpZlHWIIMS0QPIsk2saafaUxg9g3ENCd-quhtIB9OaZ18rkVKji_llssdg6FiZucvJpiPf1h0qpR-merU0It0dWCjDJmD4I6uE2LObWiuAvClJbHFeEBrz/s200/stm32-led-color-match.png"/></a></div>
STM32 <a href="https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill.html" target="_blank" rel="nofollow">Blue Pill</a> (STM32F103C8T6-development-board) circuit connections:
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpoWg1-8w0Rm7nUGUrZui32CTDwsMOnMkIIUBJDfApTgYZxoPCujODXkPUsZXCyTMVfuFiT_IINr1rOKekVHDQIcgICY_XF_lkeX1VIZ7kkzwK6xyDDMiZrEu-s9-GquwPwbjKoEp-yCoB/s964/STM32F103+-Blue+Pill+-+Marius+LEDs.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="400" data-original-height="435" data-original-width="964" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpoWg1-8w0Rm7nUGUrZui32CTDwsMOnMkIIUBJDfApTgYZxoPCujODXkPUsZXCyTMVfuFiT_IINr1rOKekVHDQIcgICY_XF_lkeX1VIZ7kkzwK6xyDDMiZrEu-s9-GquwPwbjKoEp-yCoB/s200/STM32F103+-Blue+Pill+-+Marius+LEDs.png"/></a></div>
<a href="https://www.st.com/en/development-tools/stm32cubeide.html" target="_blank" rel="nofollow">STM32CubeIDE</a> Project:
<style type="text/css">
.gist {width:420px !important;}
.gist-file
.gist-data {max-height: 360px;max-width: 420px;}
</style>
<script src="https://gist.github.com/julznc/4471de2066555889899c634b0f65de13.js?file=stm32_leds.ioc"></script>
main.c:
<script src="https://gist.github.com/julznc/4471de2066555889899c634b0f65de13.js?file=main.c"></script>
'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com6tag:blogger.com,1999:blog-3967613250975275925.post-42530971322103135922020-04-14T09:05:00.001+08:002020-04-14T09:16:36.369+08:00TVplus Go on Windows 10 PCPart 2 of <a href="https://projectproto.blogspot.com/2019/12/tvplus-go-on-laptop.html">TVplus Go on Laptop</a><br />
<br />
Using VirtualBox running Android-x86 guest OS on a <b>Windows 10</b> PC.<br />
Guides:<br />
1. <a href="https://www.android-x86.org/documentation/virtualbox.html">Android-x86 via VirtualBox</a><br />
2. <a href="https://www.lifewire.com/fix-android-screen-resolution-virtualbox-2202050">Adjust screen resolution</a>. TVplusgo app runs better on 16:9 resolutions (e.g. 1280x720).<br />
3. <a href="https://stackoverflow.com/questions/49634762/how-to-install-libhoudini-on-a-custom-android-x86-rig">Enable native bridge</a> (ARM translation layer)<br />
4. <a href="https://www.reddit.com/r/Androidx86/comments/78eiu2/run_android_x86_without_root/">Disable root</a> or <a href="https://asdasd.page/2018/02/18/Install-Magisk-on-Android-x86/">hide root via Magisk</a> (note: install only <b>v1.0.28 or older</b> of the TVplusgo app).<br />
5. <a href="https://forums.virtualbox.org/viewtopic.php?f=35&t=82639">VirtualBox USB pass-through</a> (the official android emulator for Windows, or the Qemu itself, currently does not support <a href="https://android.googlesource.com/platform/external/qemu/+/emu-master-dev/hw/usb/host-libusb.c#251">USB pass-through</a>).<br />
<br />
<iframe width="420" height="236" src="https://www.youtube.com/embed/Y5Dbzb9_wk8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com8tag:blogger.com,1999:blog-3967613250975275925.post-58654736052908516202020-01-07T08:48:00.000+08:002020-01-07T09:06:15.677+08:00TVplus Go TeardownTeardown of <a href="https://tvplusgo.abs-cbn.com/" target="_blank">ABS-CBN TVplus Go</a> USB dongle. This dongle looks like <a href="https://www.adth.com/adth-introduces-dgi-1011-dtv-receiver-for-smart-devices/" target="_blank">ADTH DGI 1011</a> (<i>*although the PCB indicates "DGI1012_RevD</i>" instead).<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPrzH8HQ1AaPLMDKatYgRygYOKYPXSi-HjRnnpVxxdhobykuRdVyd_YuoMIGHnVL91dgORNTo5tApMBC4I51BRo_5QftEPcSLcX44mYRMU8g1xXvl1qoCB-hbKIR9v8zFc6pHW3PV3sslp/s1600/IMG_20191230_103400.jpg" imageanchor="1"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPrzH8HQ1AaPLMDKatYgRygYOKYPXSi-HjRnnpVxxdhobykuRdVyd_YuoMIGHnVL91dgORNTo5tApMBC4I51BRo_5QftEPcSLcX44mYRMU8g1xXvl1qoCB-hbKIR9v8zFc6pHW3PV3sslp/s320/IMG_20191230_103400.jpg" width="320" /></a><br />
<br />
dmesg log when plugged:<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">[ 2555.447630] usb 1-1: new high-speed USB device number 13 using xhci_hcd
[ 2555.601320] usb 1-1: New USB device found, idVendor=048d, idProduct=9308, bcdDevice= 1.00
[ 2555.601325] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2555.601329] usb 1-1: Product: DGI1011
[ 2555.601331] usb 1-1: Manufacturer: Atlanta DTH, Inc.
[ 2555.601333] usb 1-1: SerialNumber: 000000
</pre>
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaLdvx7a-E1L8ke_3t_J8xjHLOBjizF4xO8ABPD-QDsb2dguFsoc7VNRQWpm8Gf0D6dYC-c8ea5z80bhDl3MqSPG0maOgOqfej9SwZO-jvVLbKpldj366EBu4Snds6OpkqpClshyrizbo8/s1600/IMG_20191230_102650.jpg" imageanchor="1"><img border="0" data-original-height="1202" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaLdvx7a-E1L8ke_3t_J8xjHLOBjizF4xO8ABPD-QDsb2dguFsoc7VNRQWpm8Gf0D6dYC-c8ea5z80bhDl3MqSPG0maOgOqfej9SwZO-jvVLbKpldj366EBu4Snds6OpkqpClshyrizbo8/s320/IMG_20191230_102650.jpg" width="320" /></a><br />
<br />
The USB chip has a marking of "Tolka101" - most probably developed by <a href="https://tolka.tv/" target="_blank">Tolka Taiwan Inc.</a> <i>- same company who develops the <a href="https://play.google.com/store/apps/details?id=com.tolka.abstv&hl=en" target="_blank">tvplus go app</a> (?)</i>. Beside this chip looks like an external EEPROM chip. (<i>*there are no markings on the RF frontend chip</i>).<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZSClZwdhBUVa74xEzNRcyjOEkiQgjhSEJz-tA3Vz1rPVH6eBCqYCBsoms69UR5zap0SRaH4pnekli5ugrmMyOZ4V5YDh4Yy-fhg3SpZUmEwb9OxM64FyTmsjId81Rr1qpoUhfeycLS7Y/s1600/IMG_20191230_112018.jpg" imageanchor="1"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZSClZwdhBUVa74xEzNRcyjOEkiQgjhSEJz-tA3Vz1rPVH6eBCqYCBsoms69UR5zap0SRaH4pnekli5ugrmMyOZ4V5YDh4Yy-fhg3SpZUmEwb9OxM64FyTmsjId81Rr1qpoUhfeycLS7Y/s320/IMG_20191230_112018.jpg" width="320" /></a><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwg76ib-dm-O6dTfS5GOUlvr2iw4F4SRb-1moliM0pTiqbPwYf8g6W2st6ba4DjmMfBEw1OZLB1XsO3P-Ef_jKeanovkLJviOMSBHZWhm9jlzaGWTfkDJN8608K-KbMmzyTtRSIh1hosvJ/s1600/IMG_20191230_103624.jpg" imageanchor="1"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwg76ib-dm-O6dTfS5GOUlvr2iw4F4SRb-1moliM0pTiqbPwYf8g6W2st6ba4DjmMfBEw1OZLB1XsO3P-Ef_jKeanovkLJviOMSBHZWhm9jlzaGWTfkDJN8608K-KbMmzyTtRSIh1hosvJ/s320/IMG_20191230_103624.jpg" width="320" /></a><br />
<br />
For simple modification, I replaced the micro-USB connector with an "older" (but more reliable) type-A USB connector+cable - more suitable since I'm using the dongle on <a href="https://projectproto.blogspot.com/2019/12/tvplus-go-on-laptop.html" target="_blank">laptop or PC</a> more often than my android phone.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZAuB1_ABKcPNafhtcmIqzatguWfhD5_lqA_ipCMlVmQUD8jpXjrnfEYVY7cN3IFBG-c0KJgbbkIuS5woLRKHVdNzKIkTtk1rrhQS9aDowT6bulV62w7znk4yBRvmmt3Kfp1pBtahjgFy1/s1600/IMG_20200104_160538.jpg" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZAuB1_ABKcPNafhtcmIqzatguWfhD5_lqA_ipCMlVmQUD8jpXjrnfEYVY7cN3IFBG-c0KJgbbkIuS5woLRKHVdNzKIkTtk1rrhQS9aDowT6bulV62w7znk4yBRvmmt3Kfp1pBtahjgFy1/s320/IMG_20200104_160538.jpg" width="240" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9J149H0HT-eL_wsL477uJg60F5_zB4-dQCkKFtvb7nEh6L44_jG5sEcFsxuUtTOOdz7vICdf0oJTP0lRNLvRr3wrEAN4SzUsDUGsnhrvK2f5C-aLmmf7k7wXXdrH1AhijFe5uPIyDNPsE/s1600/IMG_20200105_084751.jpg" imageanchor="1"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9J149H0HT-eL_wsL477uJg60F5_zB4-dQCkKFtvb7nEh6L44_jG5sEcFsxuUtTOOdz7vICdf0oJTP0lRNLvRr3wrEAN4SzUsDUGsnhrvK2f5C-aLmmf7k7wXXdrH1AhijFe5uPIyDNPsE/s320/IMG_20200105_084751.jpg" width="320" /></a>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com2tag:blogger.com,1999:blog-3967613250975275925.post-80271636406592898782019-12-29T10:17:00.000+08:002020-01-07T08:16:37.811+08:00TVplus Go on LaptopWatch free ISDB-T digital TV on laptop (or any x86_64 computer) using the <a href="https://tvplusgo.abs-cbn.com/" target="_blank">ABS-CBN TVplus Go</a> USB dongle.<br />
<br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="270" src="https://www.youtube.com/embed/SKD1_wTjDuI" width="480"></iframe><br />
<br />
As of this writing, the TVplus Go dongle only works on Android operating system. So the way to make it work on an x86 platform is either install the <a href="https://www.android-x86.org/" target="_blank">Android-x86</a> or simply use an Android emulator. This demo will use the <a href="https://developer.android.com/studio/run/emulator" target="_blank">official emulator</a> running on <a href="https://ubuntu.com/download/desktop" target="_blank">Ubuntu 18.04</a> 64-bit host OS. Other OS types, like Windows 10, might also work but will still initially require *nix-based tools for modifying the virtual device's ramdisk cpio archive and system ext4 image file.<br />
<br />
The <a href="https://play.google.com/store/apps/details?id=com.tolka.abstv&hl=en" target="_blank">TVplus Go Android app</a>, as of version 1.0.28, only works on ARM CPUs (armeabi-v7a and arm64-v8a only). Running the ARM emulator is not advisable because it's too slow and unusable. So the only option now is to install <a href="https://github.com/Rprop/libhoudini">libhoudini</a> (ARM translator) on the x86 emulator.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfxSBmJhVcu5rHK0Ly3k0m9OvP3l5pfAxFp18_91W-SkfgyHn-cnLESak_IVsqrnhrUPocPeBU0srpF4vP4ihCp4vAdr1nOjFUl9fAM-nHIMMoW4FWpwWHEOByx0ZVV0oGo02G_0gRvr0c/s1600/IMG_20191229_093306.jpg" imageanchor="1"><img border="0" data-original-height="1202" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfxSBmJhVcu5rHK0Ly3k0m9OvP3l5pfAxFp18_91W-SkfgyHn-cnLESak_IVsqrnhrUPocPeBU0srpF4vP4ihCp4vAdr1nOjFUl9fAM-nHIMMoW4FWpwWHEOByx0ZVV0oGo02G_0gRvr0c/s320/IMG_20191229_093306.jpg" width="320" /></a><br />
<br />
<b>Guide</b>:<br />
1. Download the Android command line tools (<i>installing the whole Android studio is only optional</i>).<br />
<a href="https://developer.android.com/studio#downloads" target="_blank">https://developer.android.com/studio</a>, e.g. extract <a href="https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip">sdk-tools-linux-4333796.zip</a> to <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">~/android/sdk</span>.<br />
<br />
2. Open a terminal, change directory to <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">~/android/sdk</span>, and set the following environment variables:<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee'
$ export ANDROID_HOME=$HOME/android/sdk
$ export ANDROID_SDK_ROOT=$ANDROID_HOME
</pre><br />
3. Download the emulator, platform-tools, and the system-image. Android Nougat (API-25) is selected because easier to modify compared to with the recent versions.<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ ./tools/bin/sdkmanager "platform-tools" "platforms;android-25" "emulator"
$ ./tools/bin/sdkmanager --install "system-images;android-25;google_apis;x86_64"
</pre><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtl9yMbekjG4IVfKjLCysFsAhFaxME_EkqHkC5NSRTQtc519W20dbYnr7hmakYNU563VkIO_pkiBoU-XUC2Mz9omyeXXIkOrhpnDCLRyPW-HbTpAq_cCS3whofmpEOKPk9DWCCxln42Dtu/s1600/sdkmanager.png" imageanchor="1"><img border="0" data-original-height="176" data-original-width="1043" height="54" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtl9yMbekjG4IVfKjLCysFsAhFaxME_EkqHkC5NSRTQtc519W20dbYnr7hmakYNU563VkIO_pkiBoU-XUC2Mz9omyeXXIkOrhpnDCLRyPW-HbTpAq_cCS3whofmpEOKPk9DWCCxln42Dtu/s320/sdkmanager.png" width="320" /></a><br />
<br />
4. Go to <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">$ANDROID_SDK_ROOT/system-images/android-25/google_apis/x86_64</span> and increase the size of the <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">system.img</span> (<i>create a backup first!</i>). Allocate at least 128MB for the additional files.<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ cd $ANDROID_SDK_ROOT/system-images/android-25/google_apis/x86_64
$ dd if=/dev/zero bs=1M count=512 >> ./system.img
$ e2fsck -f system.img
$ resize2fs system.img
</pre><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9w2RFLLhDioK4gZpKQ8zWQpiHVv9hZFTjqI-jnZU62GJvN31NyNDBNIWplTZGwWnRvhQ6I5P78GxTCacRWHThj3K8Ieq7oA2jnG885powkJDPPDQ9-of482KljfqC6-72wSyib67E9ssf/s1600/resize-system-image.png" imageanchor="1"><img border="0" data-original-height="302" data-original-width="1042" height="93" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9w2RFLLhDioK4gZpKQ8zWQpiHVv9hZFTjqI-jnZU62GJvN31NyNDBNIWplTZGwWnRvhQ6I5P78GxTCacRWHThj3K8Ieq7oA2jnG885powkJDPPDQ9-of482KljfqC6-72wSyib67E9ssf/s320/resize-system-image.png" width="320" /></a><br />
<br />
5. Copy <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">libhoudini</span> binaries. Mount first the <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">system.img</span> before extracting the files.<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ wget http://dl.android-x86.org/houdini/7_y/houdini.sfs -O houdini_7_y.sfs
$ mkdir -p systemfs
$ sudo mount -o loop -t ext4 system.img systemfs
$ sudo unsquashfs -d systemfs/lib/arm houdini_7_y.sfs
$ sudo cp systemfs/lib/arm/libhoudini.so systemfs/lib/
$ sudo cp systemfs/lib/arm/houdini systemfs/bin/
</pre><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkVww68xKaFgsbM4N5ZKKbCuDIuxZy_Vr7_n9Jwz69A7ZSCpdQVbEA8rjjFyeFMd2UR-9hk9586XLOix1PEnT_myjEaSG9X5WGlsRuTMflwpiVDkgPw9dsZS-J29hCjDPUFQYdbQLZY-Ct/s1600/libhoudini-copy.png" imageanchor="1"><img border="0" data-original-height="497" data-original-width="1041" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkVww68xKaFgsbM4N5ZKKbCuDIuxZy_Vr7_n9Jwz69A7ZSCpdQVbEA8rjjFyeFMd2UR-9hk9586XLOix1PEnT_myjEaSG9X5WGlsRuTMflwpiVDkgPw9dsZS-J29hCjDPUFQYdbQLZY-Ct/s320/libhoudini-copy.png" width="320" /></a><br />
Either set the selinux to permissive (add <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">-selinux permissive</span> option on the <a href="https://developer.android.com/studio/run/emulator-commandline">emulator</a>) or set the security context of the libhoudini files.<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/bin/houdini
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/libhoudini.so
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/arm
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/arm/*
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/arm/nb/*
</pre><br />
6. Allows ARM executable file formats<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ sudo mkdir -p systemfs/etc/binfmt_misc
$ echo ":arm_dyn:M::\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x28::/system/bin/houdini:" | sudo tee systemfs/etc/binfmt_misc/arm_dyn
$ echo ":arm_exe:M::\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28::/system/bin/houdini:" | sudo tee systemfs/etc/binfmt_misc/arm_exe
$ sudo nano systemfs/build.prop
</pre>add the following properties to the <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">build.prop</span> (overwrite if existing):<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">ro.enable.native.bridge.exec=1
ro.product.cpu.abilist=x86_64,x86,armeabi-v7a,armeabi
ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi
</pre><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2J2z5ijM_BcH7rTCc1xF-w-QHMoiwjk9GOAvAcjQUdUXScXEbo-Hs1fP4KSISob8B5Ka_g0Tj0aqsBtYlcyRmwRWZERqvGrMJrjpU5KZ7RrtQ-iIbvYnC-3YtbuCuAhjNVtjKlb8TS0le/s1600/build.prop-abilist.png" imageanchor="1"><img border="0" data-original-height="141" data-original-width="1042" height="43" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2J2z5ijM_BcH7rTCc1xF-w-QHMoiwjk9GOAvAcjQUdUXScXEbo-Hs1fP4KSISob8B5Ka_g0Tj0aqsBtYlcyRmwRWZERqvGrMJrjpU5KZ7RrtQ-iIbvYnC-3YtbuCuAhjNVtjKlb8TS0le/s320/build.prop-abilist.png" width="320" /></a><br />
<br />
7. Enable access to the TVPlus Go USB dongle (vendor id 0x048d, product id 0x9308)<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ echo '<permissions><feature name="android.hardware.usb.host"/></permissions>' | sudo tee systemfs/etc/permissions/android.hardware.usb.host.xml
$ echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="048d", ATTRS{idProduct}=="9308", GROUP="kvm"' | sudo tee /etc/udev/rules.d/89-usb-android.rules
$ sudo udevadm control --reload-rules</pre><br />
8. Hide from "root-detection" and "running-on-emulator-detection"<br />
i. rename the <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">su</span> executable<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ sudo mv systemfs/xbin/su systemfs/xbin/_s_u
</pre>ii. <strike>edit again <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">build.prop</span>, check these <a href="https://stackoverflow.com/questions/2799097/how-can-i-detect-when-an-android-application-is-running-in-the-emulator">answers</a> on which properties to be modified. Replace, at least, the "generic" string from <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">ro.product.device</span> and <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">ro.build.fingerprint</span></strike>. <i>(not the actual workaround)</i><br />
<br />
iii. (optional) Install Google Play, if you want to watch the encrypted channels - need to pay P20 for the registration (in-app purchase). Copy "Phonesky.apk" from <a href="https://opengapps.org/">opengapps.org</a> to <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">systemfs/priv-app/Phonesky</span><br />
<br />
iv. finally, unmount the image.<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ sync
$ sudo umount systemfs
</pre><br />
9. Extract ramdisk, and edit <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">default.prop</span><br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ mkdir -p ramdiskfs
$ cd ramdiskfs
$ gzip -dc ../ramdisk.img | cpio -i
$ nano default.prop
</pre><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDmUwDUtwmplGkabf0rVjQfd4lK7W6J6on_X1coMLU3HjsNXRLRW6x5cfeSMGsm9qA1moEaVlHdTdpM-5xTydc4OwjUJAnBQlPkh_cAn0KfuhHH70bSo4zy3FtFZQc9u2Mq5QHOdqvqO7s/s1600/ramdisk-extract.png" imageanchor="1"><img border="0" data-original-height="90" data-original-width="1040" height="28" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDmUwDUtwmplGkabf0rVjQfd4lK7W6J6on_X1coMLU3HjsNXRLRW6x5cfeSMGsm9qA1moEaVlHdTdpM-5xTydc4OwjUJAnBQlPkh_cAn0KfuhHH70bSo4zy3FtFZQc9u2Mq5QHOdqvqO7s/s320/ramdisk-extract.png" width="320" /></a><br />
<br />
Replace <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">ro.dalvik.vm.native.bridge=0</span> with <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">ro.dalvik.vm.native.bridge=libhoudini.so</span><br />
<br />
10. Edit an init configuration file (e.g. <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">init.ranchu.rc</span>) to register the libhoudini by adding these lines:<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;"># Enable native bridge for target executables
on early-init
mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
copy /system/etc/binfmt_misc/arm_exe /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm_dyn /proc/sys/fs/binfmt_misc/register
</pre><br />
11. Repack the new ramdisk<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ cd ..
$ wget https://github.com/xiaolu/mkbootimg_tools/raw/master/mkbootfs
$ chmod +x mkbootfs
$ ./mkbootfs ./ramdiskfs | gzip > ramdisk.img
</pre><br />
12. Create the AVD named "avd_7_1_x86_64" based on "Android TV (720p)" device.<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ ./tools/bin/avdmanager --verbose create avd --force --name "avd_7_1_x86_64" --device "tv_720p" \
--package "system-images;android-25;google_apis;x86_64" --tag "google_apis" --abi "x86_64"
</pre><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuafxusKIy6qyn8-Eynwyuw7avHjb-FztVcUW6aEELeTSH8x8zxaU5DZKSh7xn5uSbiN8IAsurGOENLzkk9sdI6xbat764Nt7d8LnGRMqxo1ljpU8aQy3RCYoTcFVR0qiD9RvLZw9X4vHY/s1600/avd-create.png" imageanchor="1"><img border="0" data-original-height="307" data-original-width="1041" height="94" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuafxusKIy6qyn8-Eynwyuw7avHjb-FztVcUW6aEELeTSH8x8zxaU5DZKSh7xn5uSbiN8IAsurGOENLzkk9sdI6xbat764Nt7d8LnGRMqxo1ljpU8aQy3RCYoTcFVR0qiD9RvLZw9X4vHY/s320/avd-create.png" width="320" /></a><br />
<br />
13. Now launch the emulator.<br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ ./tools/emulator @avd_7_1_x86_64 -show-kernel -verbose -memory 2048 \
-qemu -usb -device usb-host,vendorid=0x048d,productid=0x9308
</pre><br />
14. Install the TVplus Go Android app, either via the Google Play or via <span style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em;">adb install</span><br />
<pre style="background-color: #cccccc; font-family: "courier" , monospace; font-size: 1em; overflow-x: scroll;">$ adb install ../apks/TVplus\ GO_v1.0.28_apkpure.com.apk
</pre><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxryQlO2i-KjeGzSGbUS0qyfGRegn_slEFaTixgpP6kj-jFeUvApUsCiwV0bAtevm0sgenuBP7Ty6pnOcws5nMr0I55Cb609xh7hp7aHs8vZZihcEMuRAM7frkJRnK3kMqzTRBLl2sjLO2/s1600/adb-install.png" imageanchor="1"><img border="0" data-original-height="38" data-original-width="1040" height="12" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxryQlO2i-KjeGzSGbUS0qyfGRegn_slEFaTixgpP6kj-jFeUvApUsCiwV0bAtevm0sgenuBP7Ty6pnOcws5nMr0I55Cb609xh7hp7aHs8vZZihcEMuRAM7frkJRnK3kMqzTRBLl2sjLO2/s320/adb-install.png" width="320" /></a><br />
<br />
15. Finally, plugin the TVplus Go dongle to a USB port and then launch now the app on the emulator<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz1UMsq3N7OF40BLp8No6BHOD-l0iHfBHl5Jg_9M9uVzEN9RerQ4iH-yhICh64SnlScxwP-FiZJq4H4Sz_4ZhbCgtLUB0JoT9B43PvSONxnIlakP58vzQjg6_7NmNC01Z5p1mhVenFil1D/s1600/welcome-activity.png" imageanchor="1"><img border="0" data-original-height="468" data-original-width="800" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz1UMsq3N7OF40BLp8No6BHOD-l0iHfBHl5Jg_9M9uVzEN9RerQ4iH-yhICh64SnlScxwP-FiZJq4H4Sz_4ZhbCgtLUB0JoT9B43PvSONxnIlakP58vzQjg6_7NmNC01Z5p1mhVenFil1D/s320/welcome-activity.png" width="320" /></a><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dy0TDzmF0fSV0fXPe_K6FSNHwsUg71uWLPQ8jwJ4ge26c7vWiZwrHRLxsKzzRB8219Ytvyfvcg9boT7WCrXBg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><br />
'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com4tag:blogger.com,1999:blog-3967613250975275925.post-8957974021033870192019-09-24T15:24:00.003+08:002019-09-24T15:54:28.763+08:00Alexa Local FM Radio<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
Alexa Echo Dot playing local FM radio radio stations using ESP8266 WiFi module, RDA5807 FM receiver module and audio Bluetooth transmitter. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidtXjWr2eS2l_wL1kaIK8rkjy89fHx2FgxgUbTCNLWAMhxa6P6bP3I2dXoi7lVAjlCKdSgKXB0jE_6vwq6v8vgS4u7x4MgYe9k-P61K6cfT3g1fae3qHOTVoY6IJbw062ZWuURb_0aYOZf/s1600/esp-fmradio.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="340" data-original-width="870" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidtXjWr2eS2l_wL1kaIK8rkjy89fHx2FgxgUbTCNLWAMhxa6P6bP3I2dXoi7lVAjlCKdSgKXB0jE_6vwq6v8vgS4u7x4MgYe9k-P61K6cfT3g1fae3qHOTVoY6IJbw062ZWuURb_0aYOZf/s400/esp-fmradio.png" width="400" /></a></div>
<br />
source code (Arduino):<br />
<a href="https://github.com/julznc/alexa_esp_fmradio">https://github.com/julznc/alexa_esp_fmradio</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFhABUg08oM_P0uKNayWY_wOqPAcFP8c4qJ2bsjH9CyjivDlMhCBoVFF9M44Dc9O7zt1T2F_AG0vxGsxpciBlGCkR_Hc8WI1z4VSon74J9isu8QDqnPERDC_gR_qERgEDqkXFfJJdpyeZ2/s1600/echo-dot-3rdgen.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="768" data-original-width="1024" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFhABUg08oM_P0uKNayWY_wOqPAcFP8c4qJ2bsjH9CyjivDlMhCBoVFF9M44Dc9O7zt1T2F_AG0vxGsxpciBlGCkR_Hc8WI1z4VSon74J9isu8QDqnPERDC_gR_qERgEDqkXFfJJdpyeZ2/s320/echo-dot-3rdgen.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPDYtvzxb2Kdt5P2eG4Uj3rdcBrxxjTUMk843ITQUvNe1fd7qpXH_HU23LDxuE-RT1KFXlJHBP1P9D17LSS8A69tfE3t3RYl-k-T6ML4lCnlT8AEExpaooO4XkjqTPqRjN3pxiDFUy96ZN/s1600/esp8266-rda5807.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="768" data-original-width="1024" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPDYtvzxb2Kdt5P2eG4Uj3rdcBrxxjTUMk843ITQUvNe1fd7qpXH_HU23LDxuE-RT1KFXlJHBP1P9D17LSS8A69tfE3t3RYl-k-T6ML4lCnlT8AEExpaooO4XkjqTPqRjN3pxiDFUy96ZN/s320/esp8266-rda5807.jpg" width="320" /></a></div>
suggestion for improvement:<br />
use ESP32, instead of ESP8266, since it already has built-in bluetooth functionality.<br />
<br />
references:<br />
<a href="https://bitbucket.org/xoseperez/fauxmoesp">https://bitbucket.org/xoseperez/fauxmoesp</a><br />
<a href="https://github.com/me-no-dev/ESPAsyncWebServer">https://github.com/me-no-dev/ESPAsyncWebServer</a><br />
<a href="https://github.com/mathertel/Radio">https://github.com/mathertel/Radio</a>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com6tag:blogger.com,1999:blog-3967613250975275925.post-89728295220356408742018-03-17T10:00:00.000+08:002018-03-17T17:15:40.147+08:00Set-Top-Box Remote ConfigurationsSet-top-box infrared remote configuration files for <a href="http://www.lirc.org/" rel="nofollow" target="_blank">LIRC</a> (*.conf) and <a href="https://irplus-remote.github.io/" rel="nofollow" target="_blank">irplus</a> Android app (*.irplus)<br />
<br />
ABS-CBN TV Plus (Atlanta-DTH STB)<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUfiUuZGB48PQRwho3Fc-ncsyW7vKX5hwtpABuUduXhq64K8z2VQGbcCJB7XkHMDLWGWhyM89RTx7gc8K-m0L0YbnChdw6UYSsMa2izikFQpoMyUBwMUNvdylIvBi7OkS7aLXWeBQ3LfHR/s1600/IMG_20180316_234515.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUfiUuZGB48PQRwho3Fc-ncsyW7vKX5hwtpABuUduXhq64K8z2VQGbcCJB7XkHMDLWGWhyM89RTx7gc8K-m0L0YbnChdw6UYSsMa2izikFQpoMyUBwMUNvdylIvBi7OkS7aLXWeBQ3LfHR/s320/IMG_20180316_234515.jpg" width="240" /></a></div><br />
<br />
Geniric ISDB-T STB<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyTRIU2OdNuJy1RXfenV-QzugJJcg_y5rHcHmrvlnS_uSibzpCUsq_f0NL_VC5aLY6zQz8spZG8zoPeJz2iejukR7y3FnJ2y33ApYkshvA6fByWX2Mn50vJzm1gpSTvk8P6QH-fYaaubVE/s1600/IMG_20180316_234721.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyTRIU2OdNuJy1RXfenV-QzugJJcg_y5rHcHmrvlnS_uSibzpCUsq_f0NL_VC5aLY6zQz8spZG8zoPeJz2iejukR7y3FnJ2y33ApYkshvA6fByWX2Mn50vJzm1gpSTvk8P6QH-fYaaubVE/s320/IMG_20180316_234721.jpg" width="240" /></a></div><br />
<style type="text/css">
.gist {width:400px !important;}
.gist-file
.gist-data {max-height: 360px;max-width: 400px;}
</style><br />
<script src="https://gist.github.com/julznc/a3f2fa956490a0ffda077856a313cc5a.js"></script><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfm11xsyds946NV3KK6TuXsN4dJW4csmZ9znm4NxQdcVeUJ1GmDS1KwvLskLfjxWuVN8vcA6P6i6Tv62pwJcOuwP2PC-mCD0DIcoLUtN7z_V2JZFTW60t3o9F6FzltKhA6WzAER3Sc0LK-/s1600/Screenshot_20180317-162146.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfm11xsyds946NV3KK6TuXsN4dJW4csmZ9znm4NxQdcVeUJ1GmDS1KwvLskLfjxWuVN8vcA6P6i6Tv62pwJcOuwP2PC-mCD0DIcoLUtN7z_V2JZFTW60t3o9F6FzltKhA6WzAER3Sc0LK-/s320/Screenshot_20180317-162146.png" width="180" height="320" data-original-width="900" data-original-height="1600" /></a></div>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com18tag:blogger.com,1999:blog-3967613250975275925.post-85222370345885686652017-09-13T17:22:00.002+08:002019-09-24T15:53:49.332+08:00DTLS Reverse ProxyLightweight DTLS reverse proxy server based on <a href="https://projects.eclipse.org/projects/iot.tinydtls">tinydtls</a> and <a href="https://github.com/enki/libev">libev</a>.<br />
<br />
<a href="https://github.com/julznc/dtlsproxy">https://github.com/julznc/dtlsproxy</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgso2ol_dWfotnbcPaJw9CKhoE-4kXelStbMCh2_Oz9X-7nr7XFQ5mf6-0Hm4enYBk1ThW3qdeWxUdS7wXuOyMxulfm6TYZQ1OMU31C14b1lBoKf3g3b2AJ1GXnOvLl7J_ntPY20VIo7_rj/s1600/dtls_proxy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="310" data-original-width="690" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgso2ol_dWfotnbcPaJw9CKhoE-4kXelStbMCh2_Oz9X-7nr7XFQ5mf6-0Hm4enYBk1ThW3qdeWxUdS7wXuOyMxulfm6TYZQ1OMU31C14b1lBoKf3g3b2AJ1GXnOvLl7J_ntPY20VIo7_rj/s400/dtls_proxy.png" width="400" /></a></div>
'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com9tag:blogger.com,1999:blog-3967613250975275925.post-22368906707983928242017-05-06T21:23:00.000+08:002017-05-06T21:40:30.891+08:00ATtiny IR Remote<b>ATtiny2313 Infrared Sender</b><br />
<br />
parts:<br />
<ul><li><a href="http://www.microchip.com/wwwproducts/ATtiny2313" target="_blank">ATtiny2313</a> @4MHz (internal oscillator)</li>
<li>IR LED (series with 220-ohm resistor)</li>
<li>Tact switches</li>
<li>3.7V lithium ion battery & Capacitor</li>
</ul><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIpZP8usq8HstxYTgCfCzKgRcEW6z2a42JAt_4XAyKLcWl4t4X4_fWdBrjrQRNnwyhQR8Kan4JunJOB-GqiaoEU0lGScgRFFC786UX3AhQRlmUUu2P_WYsGVh-Q301-Bh9hvLV0VqT-BVP/s1600/IMG_20170506_210258.jpg" imageanchor="1"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIpZP8usq8HstxYTgCfCzKgRcEW6z2a42JAt_4XAyKLcWl4t4X4_fWdBrjrQRNnwyhQR8Kan4JunJOB-GqiaoEU0lGScgRFFC786UX3AhQRlmUUu2P_WYsGVh-Q301-Bh9hvLV0VqT-BVP/s200/IMG_20170506_210258.jpg" width="180" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZucA_-pIy5nUtrDa7Ei2-D9JE8UB-5hY7dMYEz8jfmBztPBFCqBArDdLQlUjaIfhy7sDmpeiH2q24F_CeBRUxSjk9pjFmibWSpbG-3nhy7cLcIgK0if9GPrOh1YnckOD24AuvWJoccvrF/s1600/IMG_20170506_210326.jpg" imageanchor="1"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZucA_-pIy5nUtrDa7Ei2-D9JE8UB-5hY7dMYEz8jfmBztPBFCqBArDdLQlUjaIfhy7sDmpeiH2q24F_CeBRUxSjk9pjFmibWSpbG-3nhy7cLcIgK0if9GPrOh1YnckOD24AuvWJoccvrF/s200/IMG_20170506_210326.jpg" width="180" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim_gzzGZ7Iq9EuvNsTOR8vVA8Fd6_CYiXPhz_hnun73lMDFZvGMVQeT_xJP4Lwsh3wibixAVIcC9eQKEtoQbe3KNmWJZ7FTdjeErEe7InhLwnglmHaCPd4glXqfkbXGr-hXdla074IvMBl/s1600/IMG_20170506_210809.jpg" imageanchor="1"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim_gzzGZ7Iq9EuvNsTOR8vVA8Fd6_CYiXPhz_hnun73lMDFZvGMVQeT_xJP4Lwsh3wibixAVIcC9eQKEtoQbe3KNmWJZ7FTdjeErEe7InhLwnglmHaCPd4glXqfkbXGr-hXdla074IvMBl/s200/IMG_20170506_210809.jpg" width="180" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVRXktjsmUoF-LLoLmFaK6e7GZHTrJ5oMP3jZzo5mI6354in9I4PndNkRMuAgMwN64Dh7aBe7fe4EYSSOheTqk_ISnvr-FMvdgT7tYCw4n3sw4RR3vDYwbPWu4BiyNuW6H7Aqp3qZmzbgx/s1600/IMG_20170506_210858.jpg" imageanchor="1"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVRXktjsmUoF-LLoLmFaK6e7GZHTrJ5oMP3jZzo5mI6354in9I4PndNkRMuAgMwN64Dh7aBe7fe4EYSSOheTqk_ISnvr-FMvdgT7tYCw4n3sw4RR3vDYwbPWu4BiyNuW6H7Aqp3qZmzbgx/s200/IMG_20170506_210858.jpg" width="180" /></a><br />
<br />
<style type="text/css">
.gist-file
.gist-data {max-height: 400px;}
</style><br />
avr-gcc (main.c) code:<br />
<script src="https://gist.github.com/julznc/2d750d4441182144db46685137e269af.js"></script><br />
<br />
References:<br />
<a href="http://projectproto.blogspot.com/2017/05/esp8266-ir-remote.html" target="_blank">ESP8266 IR Remote</a><br />
<a href="https://github.com/z3t0/Arduino-IRremote" target="_blank">z3t0/Arduino-IRremote</a><br />
<a href="http://www.technoblogy.com/show?KX0" target="_blank">ATtiny Low Power</a>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com4tag:blogger.com,1999:blog-3967613250975275925.post-9596361911718868202017-05-05T12:00:00.000+08:002017-05-05T12:00:28.434+08:00ESP8266 IR RemoteControl your appliances (e.g. TV and AV systems) via WiFi+IR.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzbHUuEShiKOnwvkehe61aX9gyJdPkDtuSUDrCI-A3f2onfDxqWJ4FMdscihlNaKfllb3mLe7SNz9JD9NsPQtbVnyJhqe6VUfoDvGWhw4OHCVNFmTXmAxXoMCfmkR0IqwYPd6uud2vHFEL/s1600/IRremote.jpg" imageanchor="1"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzbHUuEShiKOnwvkehe61aX9gyJdPkDtuSUDrCI-A3f2onfDxqWJ4FMdscihlNaKfllb3mLe7SNz9JD9NsPQtbVnyJhqe6VUfoDvGWhw4OHCVNFmTXmAxXoMCfmkR0IqwYPd6uud2vHFEL/s320/IRremote.jpg" width="360" /></a><br />
<br />
<style type="text/css">
.gist-file
.gist-data {max-height: 400px;}
</style><br />
Arduino code:<br />
<script src="https://gist.github.com/julznc/0575a59733d9a1393bc002b686a3e766.js"></script><br />
<br />
References:<br />
<a href="https://github.com/markszabo/IRremoteESP8266" target="_blank">markszabo/IRremoteESP8266</a><br />
<a href="http://www.hifi-remote.com/sony/" target="_blank">Sony IR codes</a><br />
<a href="http://picprojects.org.uk/projects/sirc/sonysirc.pdf" target="_blank">Sony SIRC protocol</a><br />
<br />
<br />
<br />
<br />
<br />
'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com2tag:blogger.com,1999:blog-3967613250975275925.post-81479043358453281712017-01-29T16:19:00.000+08:002017-05-05T09:55:57.346+08:00WiFi RGB MatrixHere's a DIY flexible 36x8 RGB-LED-matrix controlled via WiFi connection using an ESP8266 module.<br />
<br />
<iframe width="400" height="224" src="https://www.youtube.com/embed/fPySpf3LA5c" frameborder="0" allowfullscreen></iframe><br />
<br />
Arduino Code: <a href="https://github.com/julznc/wifi_rgb_matrix">julznc/wifi_rgb_matrix</a><br />
<br />
<br />
Assembly:<br />
<table><tbody>
<tr> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLhJhbT2reoo4kuhjbAQmnWwnLOPHjZEWlqH22u4Nz2Bo5a3YesnPPPM05CNTcnv843Tp32MIogCOJ8TLBAcI0-7wo-jZj7er0ljI2I-Pd-7g_zJBl0vthTuICzXa7Bu2kKGjTjXdfvjhk/s1600/assembly-09.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLhJhbT2reoo4kuhjbAQmnWwnLOPHjZEWlqH22u4Nz2Bo5a3YesnPPPM05CNTcnv843Tp32MIogCOJ8TLBAcI0-7wo-jZj7er0ljI2I-Pd-7g_zJBl0vthTuICzXa7Bu2kKGjTjXdfvjhk/s200/assembly-09.jpg" width="120" height="90" /></a></td> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR7dWYQP8VdtRR9P_i2x8vDqV-8Y_7ex6Sdx1Pm1mJ8OjlUeH3fjy8-oN4gUA3nwKR5teDiAQP5U-jllDhTcFhGhYkn-w_UheomI6foleaAyQ2SFptvdA0ZGhuM4ZAGUYLieLCrF5vH2lI/s1600/assembly-02.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR7dWYQP8VdtRR9P_i2x8vDqV-8Y_7ex6Sdx1Pm1mJ8OjlUeH3fjy8-oN4gUA3nwKR5teDiAQP5U-jllDhTcFhGhYkn-w_UheomI6foleaAyQ2SFptvdA0ZGhuM4ZAGUYLieLCrF5vH2lI/s200/assembly-02.jpg" width="120" height="90" /></a></td> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHJca1U1vDMiZoNtfTNyj4q2W0QkpVoAeq4HSJ5fi2i28pwbwnwY70GoMcTwcFAy_ZhqYo4FV1IKve-RzAPfU4BZSxIe86fiCCqHYoXPrSsIOW4XaKSFwinKNMfIDVvhZtCUk3Op8brtOs/s1600/assembly-01.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHJca1U1vDMiZoNtfTNyj4q2W0QkpVoAeq4HSJ5fi2i28pwbwnwY70GoMcTwcFAy_ZhqYo4FV1IKve-RzAPfU4BZSxIe86fiCCqHYoXPrSsIOW4XaKSFwinKNMfIDVvhZtCUk3Op8brtOs/s200/assembly-01.jpg" width="120" height="90" /></a></td> </tr>
<tr> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyR0phFCetTHZzIdGB2Cdq6Zmorlb7DqTPB8UoTLBT5UM_5tu_gDdTTmsi6tc1oLpSjX1VDkFFrLUrpKcUXbFb01cJYo-BXkH7s-VQq5R2fw5ZXaF0Ky2vWsyoHd3ifxpw0Vr3q4ntUflV/s1600/assembly-03.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyR0phFCetTHZzIdGB2Cdq6Zmorlb7DqTPB8UoTLBT5UM_5tu_gDdTTmsi6tc1oLpSjX1VDkFFrLUrpKcUXbFb01cJYo-BXkH7s-VQq5R2fw5ZXaF0Ky2vWsyoHd3ifxpw0Vr3q4ntUflV/s200/assembly-03.jpg" width="120" height="90" /></a></td> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAmqY7im02bX9IKP2cDnLOSL2hJNXtv7QGHhozuCaT_uhgqOpGd2afvWiIMPkjY-JMrAE-Lqgukn2shtDIk54MT7w_yKA_Up4FnmGKSBMOpWjqt-CbCznOxqiKk4q28_vhYghk7K3ZnkOC/s1600/assembly-04.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAmqY7im02bX9IKP2cDnLOSL2hJNXtv7QGHhozuCaT_uhgqOpGd2afvWiIMPkjY-JMrAE-Lqgukn2shtDIk54MT7w_yKA_Up4FnmGKSBMOpWjqt-CbCznOxqiKk4q28_vhYghk7K3ZnkOC/s200/assembly-04.jpg" width="120" height="90" /></a></td> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidbxlf_K8YQwZ2syugmns6rm4JWNHFaa9xhXCVR9SZg9Ekxmq8jZqnrpXGyFaQF8vz-5JEpmLWFQ63OWI76ythiBCrdMOvx92jywntjrGi53B6Rw5yW8CtIfa2Sao0UeBXqqbnmbE7gw_v/s1600/assembly-05.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidbxlf_K8YQwZ2syugmns6rm4JWNHFaa9xhXCVR9SZg9Ekxmq8jZqnrpXGyFaQF8vz-5JEpmLWFQ63OWI76ythiBCrdMOvx92jywntjrGi53B6Rw5yW8CtIfa2Sao0UeBXqqbnmbE7gw_v/s200/assembly-05.jpg" width="120" height="90" /></a></td> </tr>
<tr> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWW2JwEGUx9zyDp4BnuNc0nTKmDbCPnC2WIwgxA4Zii8g9gBm8AKjh0Oxxi22MKpXsH_h2FxPFdtXYaAVYzr53kcBNM-XsqKrMjczgVwEoY82c2N5kzUhxf611fcFkZVvmsF4QbpKfUypv/s1600/assembly-06.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWW2JwEGUx9zyDp4BnuNc0nTKmDbCPnC2WIwgxA4Zii8g9gBm8AKjh0Oxxi22MKpXsH_h2FxPFdtXYaAVYzr53kcBNM-XsqKrMjczgVwEoY82c2N5kzUhxf611fcFkZVvmsF4QbpKfUypv/s200/assembly-06.jpg" width="120" height="90" /></a></td> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPjBmR6IsbzW6zSqw1gzTG5KTKz0Vc4wMQExXbg0sP0EVBFS0NMoMYs8cBmE8IxWlBxxoG4PHiIWV0a7XJ6YnG5qMjPIYlMnHQbh21cO5WNfEr7lpaRDmMYwiWBrolceSsqvUQLXQho-c4/s1600/assembly-07.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPjBmR6IsbzW6zSqw1gzTG5KTKz0Vc4wMQExXbg0sP0EVBFS0NMoMYs8cBmE8IxWlBxxoG4PHiIWV0a7XJ6YnG5qMjPIYlMnHQbh21cO5WNfEr7lpaRDmMYwiWBrolceSsqvUQLXQho-c4/s200/assembly-07.jpg" width="120" height="90" /></a></td> <td align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYIh_MiMhSZkMTvO0N4Xx8x3w6rB8ZeG2y4t1lK97ZNNi3qMooSmCuFIEa29qzlEs0B4MSz0XCcL1ocwvCsTvFnpcaKxcw19wX0SblzFCbPVrjlMNiimMhr4IU2rdWzh3JUg9x3cVKP1HO/s1600/assembly-08.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYIh_MiMhSZkMTvO0N4Xx8x3w6rB8ZeG2y4t1lK97ZNNi3qMooSmCuFIEa29qzlEs0B4MSz0XCcL1ocwvCsTvFnpcaKxcw19wX0SblzFCbPVrjlMNiimMhr4IU2rdWzh3JUg9x3cVKP1HO/s200/assembly-08.jpg" width="120" height="60" /></a></td> </tr>
</tbody> </table><br />
References:<br />
<a href="https://github.com/Makuna/NeoPixelBus">NeoPixelBus</a> - for interfacing WS2812 LEDs to ESP8266 controller<br />
<a href="https://github.com/adafruit/Adafruit-GFX-Library">Adafruit-GFX-Library</a> - with font library for displaying texts<br />
<a href="http://maximumoctopus.com/electronics/builder.htm">LED Matrix Studio</a> - for creating bitmap images<br />
<br />
'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com3tag:blogger.com,1999:blog-3967613250975275925.post-42560113033778753832016-06-11T13:47:00.001+08:002016-06-11T13:51:44.733+08:00ESP8266 PWM Android ControllerControl ESP8266 PWM outputs* with Android.<br />
<br />
Android app: <a href="https://play.google.com/store/apps/details?id=com.ymsoftlabs.wifipwm" target="_blank">play.google/wifipwm</a><br />
Android src: <a href="https://github.com/julznc/esp_wifi_pwm" target="_blank">github/esp_wifi_pwm</a><br />
<br />
demo:<br />
<iframe allowfullscreen="" frameborder="0" height="auto" src="https://www.youtube.com/embed/6ohKBdNLzYI" width="auto"></iframe><br />
<br />
<a href="http://randomnerdtutorials.com/esp8266-web-server/" target="_blank">ESP8266 <b>init.lua</b></a> :<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; height: 300px; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">wifi.setmode(wifi.STATION)
wifi.sta.config(<span style="color: #aa5500;">"WIFI_SSID"</span>,<span style="color: #aa5500;">"WIFI_PASSWORD"</span>)
<span style="color: #0000aa;">local</span> GP0 = <span style="color: #009999;">3</span>
<span style="color: #0000aa;">local</span> GP2 = <span style="color: #009999;">4</span>
<span style="color: #0000aa;">local</span> port = <span style="color: #009999;">3456</span>
<span style="color: #00aaaa;">print</span>(wifi.sta.getip())
srv=net.createServer(net.UDP)
srv:on(<span style="color: #aa5500;">"receive"</span>, <span style="color: #0000aa;">function</span>(cli, rcv)
<span style="color: #aaaaaa; font-style: italic;">--print(rcv)</span>
rx={}
<span style="color: #0000aa;">for</span> i, s <span style="color: #0000aa;">in</span> <span style="color: #00aaaa;">string.gmatch</span>(rcv, <span style="color: #aa5500;">"(%w+)=(%w+)"</span>) <span style="color: #0000aa;">do</span>
rx[i]=s
<span style="color: #aaaaaa; font-style: italic;">--print(i, rx[i])</span>
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">if</span> rx.d0 <span style="color: #0000aa;">then</span>
pwm.setduty(GP0,rx.d0)
<span style="color: #aaaaaa; font-style: italic;">--print("GP0 duty",rx.d0)</span>
<span style="color: #0000aa;">elseif</span> rx.d2 <span style="color: #0000aa;">then</span>
pwm.setduty(GP2,rx.d2)
<span style="color: #aaaaaa; font-style: italic;">--print("GP2 duty",rx.d2)</span>
<span style="color: #0000aa;">elseif</span> rx.f0 <span style="color: #0000aa;">and</span> rx.c0 <span style="color: #0000aa;">then</span>
pwm.setup(GP0,rx.f0,rx.c0)
pwm.start(GP0)
<span style="color: #00aaaa;">print</span>(<span style="color: #aa5500;">"GP0 freq"</span>,rx.f0,<span style="color: #aa5500;">"cycles"</span>, rx.c0)
<span style="color: #0000aa;">elseif</span> rx.f2 <span style="color: #0000aa;">and</span> rx.c2 <span style="color: #0000aa;">then</span>
pwm.setup(GP2,rx.f2,rx.c2)
pwm.start(GP2)
<span style="color: #00aaaa;">print</span>(<span style="color: #aa5500;">"GP2 freq"</span>,rx.f2,<span style="color: #aa5500;">"cycles"</span>, rx.c2)
<span style="color: #0000aa;">end</span>
cli:send(rcv)
<span style="color: #0000aa;">end</span>)
srv:listen(port)
</pre>
</div>
<br />
<br />
*PWM outputs <a href="https://nodemcu.readthedocs.io/en/dev/en/modules/pwm/" target="_blank">nodemcu pwm</a><br />
<ul>
<li>pins GP0 and GP2</li>
<li>up to 1kHz only</li>
<li>0-100%duty (<i>note: 1023 cycles = 100% duty</i>)</li>
</ul>
<br />'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com5tag:blogger.com,1999:blog-3967613250975275925.post-28798966290036665702016-05-14T14:56:00.001+08:002016-05-14T14:57:21.236+08:00ESP8266 and SHT1x Web Interface<br />
Here's a <i>*duino-less</i> (<i>*pi-less</i>) simple project using <a href="http://www.e-gizmo.com/KIT/ESP11.htm" target="_blank">ESP11 (ESP8266) Wifi Module</a> and SHT10 humidity-temperature sensor.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsjc1SbhpmfFHdAQSH0OrVCk10lBNfyQdEcQYvQKCp2XXDf8iWHbU5OeuhDCmE7zejWuurCZoQwEqfiKtxycaR3z6-z2nFjnF6z59Z6U67Qpd77g7Om26DwXDUbPLBi98-BpG8BK-kmJTU/s1600/IMG_20160514_140808.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsjc1SbhpmfFHdAQSH0OrVCk10lBNfyQdEcQYvQKCp2XXDf8iWHbU5OeuhDCmE7zejWuurCZoQwEqfiKtxycaR3z6-z2nFjnF6z59Z6U67Qpd77g7Om26DwXDUbPLBi98-BpG8BK-kmJTU/s320/IMG_20160514_140808.jpg" width="320" /></a></div>
<br />
<br />
<b>init.lua</b>:<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; height: 360px; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">wifi.setmode(wifi.STATION)
wifi.sta.config(<span style="color: #aa5500;">"WIFI_SSID"</span>,<span style="color: #aa5500;">"WIFI_PASSWORD"</span>)
<span style="color: #0000aa;">local</span> DAT = <span style="color: #009999;">4</span>
<span style="color: #0000aa;">local</span> CLK = <span style="color: #009999;">3</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">DL</span>()
gpio.write(DAT, gpio.LOW)
gpio.mode(DAT, gpio.OUTPUT)
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">DH</span>()
gpio.mode(DAT, gpio.INPUT)
gpio.write(DAT, gpio.HIGH)
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">CL</span>()
gpio.write(CLK, gpio.LOW)
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">CH</span>()
gpio.write(CLK, gpio.HIGH)
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">DR</span>()
gpio.mode(DAT, gpio.INPUT)
<span style="color: #0000aa;">return</span> gpio.read(DAT)
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">W8</span>()
<span style="color: #0000aa;">for</span> i = <span style="color: #009999;">1</span>, <span style="color: #009999;">100</span> <span style="color: #0000aa;">do</span>
tmr.delay(<span style="color: #009999;">10000</span>)
<span style="color: #0000aa;">if</span> DR() == gpio.LOW <span style="color: #0000aa;">then</span>
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">true</span>
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">false</span>
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">RB</span>()
<span style="color: #0000aa;">local</span> val = <span style="color: #009999;">0</span>
<span style="color: #0000aa;">for</span> i = <span style="color: #009999;">0</span>, <span style="color: #009999;">7</span> <span style="color: #0000aa;">do</span>
CH()
val = val*<span style="color: #009999;">2</span> + DR()
CL()
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">return</span> val
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">function</span> <span style="color: #00aa00;">shtread</span>(cmd)
DH() CH() DL() CL() CH() DH() CL()
<span style="color: #0000aa;">for</span> i = <span style="color: #009999;">0</span>, <span style="color: #009999;">7</span> <span style="color: #0000aa;">do</span>
<span style="color: #0000aa;">if</span> bit.band(cmd, <span style="color: #009999;">2</span>^(<span style="color: #009999;">7</span>-i))==<span style="color: #009999;">0</span> <span style="color: #0000aa;">then</span>
DL()
<span style="color: #0000aa;">else</span>
DH()
<span style="color: #0000aa;">end</span>
CH() CL()
<span style="color: #0000aa;">end</span>
CH() CL()
<span style="color: #0000aa;">if</span> <span style="color: #0000aa;">not</span> W8() <span style="color: #0000aa;">then</span>
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">nil</span>
<span style="color: #0000aa;">end</span>
DH()
<span style="color: #0000aa;">local</span> val = RB()
DH() DL() CH() CL() DH()
val = val*<span style="color: #009999;">256</span> + RB()
DH() CH() CL()
<span style="color: #0000aa;">return</span> val
<span style="color: #0000aa;">end</span>
page=<span style="color: #aa5500;">[[<head><meta charset="utf-8"/></span>
<span style="color: #aa5500;"><link href="http://projectproto.blogspot.com/favicon.ico" rel="icon"/></span>
<span style="color: #aa5500;"><title>ESP+SHT</title></head></span>
<span style="color: #aa5500;"><body><h1>ESP8266 and SHT1x</h1><h2 id="T">T??</h2><h2 id="H">H??</h2></span>
<span style="color: #aa5500;"><script></span>
<span style="color: #aa5500;"> function update(){</span>
<span style="color: #aa5500;"> var xrq = new XMLHttpRequest();</span>
<span style="color: #aa5500;"> xrq.onreadystatechange=function(){</span>
<span style="color: #aa5500;"> if (xrq.readyState==4 && xrq.status==200){</span>
<span style="color: #aa5500;"> var th=JSON.parse(xrq.responseText);</span>
<span style="color: #aa5500;"> var t0=th["t"], h0=th["h"];</span>
<span style="color: #aa5500;"> var t=(t0*0.01)-39.7;</span>
<span style="color: #aa5500;"> var hl=(0.0367*h0)+(-0.0000015955*h0*h0)-2.0468;</span>
<span style="color: #aa5500;"> var h=(t-25.0)*(0.01+(0.00008*h0))+hl;</span>
<span style="color: #aa5500;"> document.getElementById("T").innerHTML="Temperature: "+t.toFixed(2)+"&deg;C";</span>
<span style="color: #aa5500;"> document.getElementById("H").innerHTML="Humidity: "+h.toFixed(2)+"%";}</span>
<span style="color: #aa5500;"> }</span>
<span style="color: #aa5500;"> xrq.open("GET","/get/sht",true);</span>
<span style="color: #aa5500;"> xrq.overrideMimeType("application/json");</span>
<span style="color: #aa5500;"> xrq.send(null);</span>
<span style="color: #aa5500;"> }setInterval(update, 1000);</span>
<span style="color: #aa5500;"></script></body>]]</span>
srv=net.createServer(net.TCP)
srv:listen(<span style="color: #009999;">80</span>,<span style="color: #0000aa;">function</span>(conn)
conn:on(<span style="color: #aa5500;">"receive"</span>, <span style="color: #0000aa;">function</span>(client,request)
<span style="color: #0000aa;">local</span> buf = <span style="color: #aa5500;">""</span>;
<span style="color: #0000aa;">local</span> _, _, mtd, path, _ = <span style="color: #00aaaa;">string.find</span>(request, <span style="color: #aa5500;">"([A-Z]+) (.+)?(.+) HTTP"</span>);
<span style="color: #0000aa;">if</span>(mtd == <span style="color: #0000aa;">nil</span>)<span style="color: #0000aa;">then</span>
_, _, mtd, path = <span style="color: #00aaaa;">string.find</span>(request, <span style="color: #aa5500;">"([A-Z]+) (.+) HTTP"</span>);
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">if</span> path == <span style="color: #aa5500;">"/"</span> <span style="color: #0000aa;">then</span>
buf = buf..page
<span style="color: #0000aa;">elseif</span> path == <span style="color: #aa5500;">"/get/sht"</span> <span style="color: #0000aa;">then</span>
t = shtread(<span style="color: #009999;">3</span>)
h = shtread(<span style="color: #009999;">5</span>)
<span style="color: #0000aa;">if</span> (t ~= <span style="color: #0000aa;">nil</span> <span style="color: #0000aa;">and</span> h ~= <span style="color: #0000aa;">nil</span>) <span style="color: #0000aa;">then</span>
buf = buf..<span style="color: #aa5500;">"{\"t\":"</span>..t..<span style="color: #aa5500;">", \"h\":"</span>..h..<span style="color: #aa5500;">"}"</span>
<span style="color: #0000aa;">end</span>
<span style="color: #0000aa;">end</span>
client:send(buf)
client:close()
<span style="color: #00aaaa;">collectgarbage</span>()
<span style="color: #0000aa;">end</span>)
<span style="color: #0000aa;">end</span>)
</pre>
</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlKSiENmVDJrulAs33qcCWR_jH3kPcIbzQ01TkZz-OZuibcZ9f9omdPlq1hcrNETOEXZC26w7WXS_e5VvD59Of-o4qleeFQ09EdMUOWEEMuJ0w6vF8FRgAbNkmV7Mu6FvrlWxcNF0M4bL8/s1600/IMG_20160514_141233.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlKSiENmVDJrulAs33qcCWR_jH3kPcIbzQ01TkZz-OZuibcZ9f9omdPlq1hcrNETOEXZC26w7WXS_e5VvD59Of-o4qleeFQ09EdMUOWEEMuJ0w6vF8FRgAbNkmV7Mu6FvrlWxcNF0M4bL8/s320/IMG_20160514_141233.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmsAdtmw9p-Py-IqEvnqCBf_t9khk8wNKe7oczjHEExb9As3XXKAHNRF-XNN9luIMli9vs-E2lsKmzTnz4ZpZdZr2XfgwPwnGX9BcTMWUyYSOUuXkUm8MOVPIvUHxKpyJJ9tUYXGdYnsQW/s1600/java_2016-05-14_12-34-21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="203" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmsAdtmw9p-Py-IqEvnqCBf_t9khk8wNKe7oczjHEExb9As3XXKAHNRF-XNN9luIMli9vs-E2lsKmzTnz4ZpZdZr2XfgwPwnGX9BcTMWUyYSOUuXkUm8MOVPIvUHxKpyJJ9tUYXGdYnsQW/s320/java_2016-05-14_12-34-21.png" width="320" /></a></div>
<br />
<br />
References:<br />
<a href="http://randomnerdtutorials.com/esp8266-web-server/" target="_blank">ESP8266 Web Server Tutorial</a><br />
<a href="https://github.com/SkyRzn/esp8266_sht10" target="_blank">Github esp8266 sht10</a><br />
<a href="http://www.e-gizmo.com/KIT/ESP11.htm" target="_blank">e-Gizmo ESP11 kit</a><br />
<a href="http://www.esp8266.com/wiki/doku.php" target="_blank">ESP8266 wiki</a><br />
<a href="https://github.com/nodemcu/nodemcu-firmware" target="_blank">NodeMCU firmware</a> <br />
<a href="https://github.com/marcoskirsch/nodemcu-httpserver" target="_blank">NodeMCU http server</a> <br />
<br />'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com11tag:blogger.com,1999:blog-3967613250975275925.post-70539445241170359142016-05-09T16:15:00.000+08:002016-05-09T16:33:24.341+08:00Android-Arduino Communication via USB OTG<br />
<span style="font-family: inherit;">USB On-the-go capability in Android devices has now become more available in the market. And why wouldn’t it be? This feature, nicknamed OTG, enables you to use your flash drives, keyboards, mice and even printers with just your phone! What’s more interesting is it can also enable you to communicate and control your microprocessors using your Android device without the need for additional modules – just a <a href="http://www.eagleg.com/micro-usb-otg-adapter-for-samsung-galaxy-s3.html?gclid=CjwKEAjw1_KwBRDEz_WvncL4jGwSJAAEym0d8K9lWRxKKIMLGRgZaFIKsTxzMgGZW89XdZunqstphhoCY0Dw_wcB">cable</a>. In this article, we will see how this communication can become possible. To demonstrate, we will control the behavior of an LED and send messages to another very popular item in the electronics world – the Arduino. </span><br />
<span style="font-family: inherit;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGQZRxw7RXrvwtXgcBzMz1VxNZq_IPG-xRsK0Ds0fsUze9F4auNRalJJUkjwifwZD6ST-3TR5zb0s48-Ym19r89rzSyUjHSgBbXirNT85zCkTu9L2-R3Un8zyzKGCeaJx_tOhD-exU1O4G/s1600/setup+pic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGQZRxw7RXrvwtXgcBzMz1VxNZq_IPG-xRsK0Ds0fsUze9F4auNRalJJUkjwifwZD6ST-3TR5zb0s48-Ym19r89rzSyUjHSgBbXirNT85zCkTu9L2-R3Un8zyzKGCeaJx_tOhD-exU1O4G/s320/setup+pic.png" width="320" /></a></div>
<br />
<span style="font-family: inherit;">The shorter end of the stick is Arduino’s side. In your Arduino, simply upload this code:</span><br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #333399; font-weight: bold;">int</span> ledPin <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">13</span>;
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">setup</span>(){
Serial.begin(<span style="color: #0000dd; font-weight: bold;">9600</span>);
Serial.setTimeout(<span style="color: #0000dd; font-weight: bold;">200</span>);
pinMode(ledPin, OUTPUT);
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">loop</span>(){
<span style="color: #008800; font-weight: bold;">if</span> (Serial.available()){
String c <span style="color: #333333;">=</span> Serial.readString();
<span style="color: #008800; font-weight: bold;">if</span> (c.equals(<span style="background-color: #fff0f0;">"TONLED"</span>)) digitalWrite(ledPin, HIGH);
<span style="color: #008800; font-weight: bold;">else</span> <span style="color: #008800; font-weight: bold;">if</span> (c.equals(<span style="background-color: #fff0f0;">"TOFFLED"</span>)) digitalWrite(ledPin, LOW);
<span style="color: #008800; font-weight: bold;">else</span> Serial.print(c);
}
}
</pre>
</div>
<br />
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
I<span style="font-family: inherit;">n the above sketch, we are simply waiting for the data arriving at our serial line and performing actions based on the data received. For instance, turning on the LED </span><span style="color: blue;"><span style="font-family: "courier new" , "courier" , monospace;">ledPin</span> </span><span style="font-family: inherit;">requires a </span><span style="color: blue;"><span style="font-family: "courier new" , "courier" , monospace;">TONLED</span> </span><span style="font-family: inherit;">message from our Android device. You’ve probably noticed that there are no special libraries or methods in our Arduino sketch. That’s a great thing because it tells us that the system is not exclusive to Arduino and will work with any microcontroller that supports serial communication.<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-family: inherit;"><br />
</span></div>
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-family: inherit;">Let’s now move on to Android’s side. The first step is to create an Android project and add the necessary components. In the project we created, we added extra components for user convenience. For learning and testing purposes, only the following are necessary:</span></div>
<div class="MsoListParagraphCxSpFirst" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in; mso-add-space: auto;">
</div>
<ul>
<li><span style="font-family: inherit; line-height: 115%;">Text Field – used to get input data by the user, which will be sent to and echoed by the Arduino</span></li>
<li><span style="font-family: inherit; line-height: 115%;">Toggle Button – used to control the behavior of the LED</span></li>
<li><span style="font-family: inherit; line-height: 115%;">Start Button – used to open the serial port</span></li>
<li><span style="font-family: inherit; line-height: 115%;">Send Button – used to send messages to Arduino</span></li>
<li><span style="font-family: inherit; line-height: 115%;">Text View – used to display logs</span></li>
</ul>
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-family: inherit;">To simplify the setup and processes, we will use the <a href="https://github.com/felHR85/UsbSerial/releases">UsbSerial</a> library by felHR85. There are a lot of libraries you can choose from. In case you have other preferences, feel free to modify and adapt to your preferred library. <o:p></o:p></span><br />
<span style="font-family: inherit;"><br />
</span></div>
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-family: inherit;">In the build.gradle of your project, add jitpack. <a href="https://jitpack.io/">Jitpack</a> is a very awesome tool that enables us to get a Git project into our build.</span></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">allprojects <span style="color: #333333;">{</span>
repositories <span style="color: #333333;">{</span>
jcenter<span style="color: #333333;">()</span>
maven <span style="color: #333333;">{</span> url <span style="background-color: #fff0f0;">"https://jitpack.io"</span> <span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
</pre>
</div>
<br />
<span style="font-family: inherit;">Now, add the dependency to your module’s build.gradle.</span><br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">compile <span style="background-color: #ffaaaa; color: red;">'</span>com<span style="color: #333333;">.</span><span style="color: #0000cc;">github</span><span style="color: #333333;">.</span><span style="color: #0000cc;">felHR85</span><span style="color: #333333;">:</span><span style="color: #997700; font-weight: bold;">UsbSerial:</span><span style="color: #6600ee; font-weight: bold;">4.3</span><span style="background-color: #ffaaaa; color: red;">'</span>
</pre>
</div>
<br />
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-family: inherit;">Moving on to our main activity, there are some variables that we wish to declare globally for convenience.</span></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">private</span> <span style="color: #008800; font-weight: bold;">static</span> <span style="color: #008800; font-weight: bold;">final</span> String ACTION_USB_PERMISSION <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"com.android.example.USB_PERMISSION"</span><span style="color: #333333;">;</span>
UsbDevice device<span style="color: #333333;">;</span>
UsbDeviceConnection connection<span style="color: #333333;">;</span>
UsbManager usbManager<span style="color: #333333;">;</span>
UsbSerialDevice serialPort<span style="color: #333333;">;</span>
PendingIntent pendingIntent<span style="color: #333333;">;</span>
</pre>
</div>
<br />
<span style="font-family: inherit;">The next items that we will present here will not be discussed thoroughly, but you can refer to <a href="http://developer.android.com/guide/topics/connectivity/usb/host.html">Android's official documentation</a> for details.</span><br />
<span style="font-family: inherit;"><br />
</span> <span style="font-family: inherit;">Before trying to start the communication, you must seek permission from the user. To do this, create a broadcast receiver. This receiver listens for the intent that gets broadcasted when you call </span><span style="color: blue; font-family: "courier new" , "courier" , monospace;">requestPermission()</span><span style="font-family: inherit;">. Only when granted can we proceed to opening the connection and setting parameters for the Serial communication.</span><br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">private</span> <span style="color: #008800; font-weight: bold;">final</span> BroadcastReceiver broadcastReceiver <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">new</span> BroadcastReceiver<span style="color: #333333;">()</span> <span style="color: #333333;">{</span>
<span style="color: #555555; font-weight: bold;">@Override</span>
<span style="color: #008800; font-weight: bold;">public</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">onReceive</span><span style="color: #333333;">(</span>Context context<span style="color: #333333;">,</span> Intent intent<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>intent<span style="color: #333333;">.</span><span style="color: #0000cc;">getAction</span><span style="color: #333333;">().</span><span style="color: #0000cc;">equals</span><span style="color: #333333;">(</span>ACTION_USB_PERMISSION<span style="color: #333333;">))</span> <span style="color: #333333;">{</span>
<span style="color: #333399; font-weight: bold;">boolean</span> granted <span style="color: #333333;">=</span> intent<span style="color: #333333;">.</span><span style="color: #0000cc;">getExtras</span><span style="color: #333333;">().</span><span style="color: #0000cc;">getBoolean</span><span style="color: #333333;">(</span>UsbManager<span style="color: #333333;">.</span><span style="color: #0000cc;">EXTRA_PERMISSION_GRANTED</span><span style="color: #333333;">);</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>granted<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
connection <span style="color: #333333;">=</span> usbManager<span style="color: #333333;">.</span><span style="color: #0000cc;">openDevice</span><span style="color: #333333;">(</span>device<span style="color: #333333;">);</span>
serialPort <span style="color: #333333;">=</span> UsbSerialDevice<span style="color: #333333;">.</span><span style="color: #0000cc;">createUsbSerialDevice</span><span style="color: #333333;">(</span>device<span style="color: #333333;">,</span> connection<span style="color: #333333;">);</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>serialPort <span style="color: #333333;">!=</span> <span style="color: #008800; font-weight: bold;">null</span><span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">open</span><span style="color: #333333;">())</span> <span style="color: #333333;">{</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">setBaudRate</span><span style="color: #333333;">(</span><span style="color: #0000dd; font-weight: bold;">9600</span><span style="color: #333333;">);</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">setDataBits</span><span style="color: #333333;">(</span>UsbSerialInterface<span style="color: #333333;">.</span><span style="color: #0000cc;">DATA_BITS_8</span><span style="color: #333333;">);</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">setStopBits</span><span style="color: #333333;">(</span>UsbSerialInterface<span style="color: #333333;">.</span><span style="color: #0000cc;">STOP_BITS_1</span><span style="color: #333333;">);</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">setParity</span><span style="color: #333333;">(</span>UsbSerialInterface<span style="color: #333333;">.</span><span style="color: #0000cc;">PARITY_NONE</span><span style="color: #333333;">);</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">setFlowControl</span><span style="color: #333333;">(</span>UsbSerialInterface<span style="color: #333333;">.</span><span style="color: #0000cc;">FLOW_CONTROL_OFF</span><span style="color: #333333;">);</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">read</span><span style="color: #333333;">(</span>mCallback<span style="color: #333333;">);</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #333333;">{</span>
Log<span style="color: #333333;">.</span><span style="color: #0000cc;">d</span><span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"SERIAL"</span><span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">"PORT NOT OPEN"</span><span style="color: #333333;">);</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #333333;">{</span>
Log<span style="color: #333333;">.</span><span style="color: #0000cc;">d</span><span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"SERIAL"</span><span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">"PORT IS NULL"</span><span style="color: #333333;">);</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #333333;">{</span>
Log<span style="color: #333333;">.</span><span style="color: #0000cc;">d</span><span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"SERIAL"</span><span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">"PERMISSION NOT GRANTED"</span><span style="color: #333333;">);</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>intent<span style="color: #333333;">.</span><span style="color: #0000cc;">getAction</span><span style="color: #333333;">().</span><span style="color: #0000cc;">equals</span><span style="color: #333333;">(</span>UsbManager<span style="color: #333333;">.</span><span style="color: #0000cc;">ACTION_USB_DEVICE_ATTACHED</span><span style="color: #333333;">))</span> <span style="color: #333333;">{</span>
onClickStart<span style="color: #333333;">(</span>startButton<span style="color: #333333;">);</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>intent<span style="color: #333333;">.</span><span style="color: #0000cc;">getAction</span><span style="color: #333333;">().</span><span style="color: #0000cc;">equals</span><span style="color: #333333;">(</span>UsbManager<span style="color: #333333;">.</span><span style="color: #0000cc;">ACTION_USB_DEVICE_DETACHED</span><span style="color: #333333;">))</span> <span style="color: #333333;">{</span>
<span style="color: #888888;">//can add something to close the connection</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">};</span>
<span style="color: #333333;">};</span>
</pre>
</div>
<br />
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-family: inherit;">On your </span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: blue; font-family: "courier new";">onCreate</span> </span><span style="font-family: inherit;">method, declare the intent and register your broadcast receiver to start and stop the serial connection.</span></div>
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">pendingIntent <span style="color: #333333;">=</span> PendingIntent<span style="color: #333333;">.</span><span style="color: #0000cc;">getBroadcast</span><span style="color: #333333;">(</span><span style="color: #008800; font-weight: bold;">this</span><span style="color: #333333;">,</span> <span style="color: #0000dd; font-weight: bold;">0</span><span style="color: #333333;">,</span> <span style="color: #008800; font-weight: bold;">new</span> Intent<span style="color: #333333;">(</span>ACTION_USB_PERMISSION<span style="color: #333333;">),</span> <span style="color: #0000dd; font-weight: bold;">0</span><span style="color: #333333;">);</span>
IntentFilter filter <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">new</span> IntentFilter<span style="color: #333333;">(</span>ACTION_USB_PERMISSION<span style="color: #333333;">);</span>
registerReceiver<span style="color: #333333;">(</span>broadcastReceiver<span style="color: #333333;">,</span> filter<span style="color: #333333;">);</span>
</pre>
</div>
<br />
<div class="MsoNormal" style="line-height: 115%; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-family: inherit;">In our application, we created a start button to start the connection when pressed. In the method that corresponds to the </span><span style="color: blue; font-family: "courier new" , "courier" , monospace;">onClick </span><span style="font-family: inherit;">action of our button, we add the following:</span></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">public</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">onClickStart</span><span style="color: #333333;">(</span>View view<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(!</span>isSerialStarted<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
usbManager <span style="color: #333333;">=</span> <span style="color: #333333;">(</span>UsbManager<span style="color: #333333;">)</span> getSystemService<span style="color: #333333;">(</span>Context<span style="color: #333333;">.</span><span style="color: #0000cc;">USB_SERVICE</span><span style="color: #333333;">);</span>
HashMap<span style="color: #333333;"><</span>String<span style="color: #333333;">,</span> UsbDevice<span style="color: #333333;">></span> usbDevices <span style="color: #333333;">=</span> usbManager<span style="color: #333333;">.</span><span style="color: #0000cc;">getDeviceList</span><span style="color: #333333;">();</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(!</span>usbDevices<span style="color: #333333;">.</span><span style="color: #0000cc;">isEmpty</span><span style="color: #333333;">())</span> <span style="color: #333333;">{</span>
<span style="color: #333399; font-weight: bold;">boolean</span> keep <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">true</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">for</span> <span style="color: #333333;">(</span>Map<span style="color: #333333;">.</span><span style="color: #0000cc;">Entry</span><span style="color: #333333;"><</span>String<span style="color: #333333;">,</span> UsbDevice<span style="color: #333333;">></span> entry <span style="color: #333333;">:</span> usbDevices<span style="color: #333333;">.</span><span style="color: #0000cc;">entrySet</span><span style="color: #333333;">())</span> <span style="color: #333333;">{</span>
device <span style="color: #333333;">=</span> entry<span style="color: #333333;">.</span><span style="color: #0000cc;">getValue</span><span style="color: #333333;">();</span>
<span style="color: #333399; font-weight: bold;">int</span> deviceVID <span style="color: #333333;">=</span> device<span style="color: #333333;">.</span><span style="color: #0000cc;">getVendorId</span><span style="color: #333333;">();</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>deviceVID <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">1027</span> <span style="color: #333333;">||</span> deviceVID <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">9025</span><span style="color: #333333;">)</span> <span style="color: #333333;">{</span> <span style="color: #888888;">//Arduino Vendor ID</span>
usbManager<span style="color: #333333;">.</span><span style="color: #0000cc;">requestPermission</span><span style="color: #333333;">(</span>device<span style="color: #333333;">,</span> pendingIntent<span style="color: #333333;">);</span>
keep <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">false</span><span style="color: #333333;">;</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #333333;">{</span>
connection <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">null</span><span style="color: #333333;">;</span>
device <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">null</span><span style="color: #333333;">;</span>
<span style="color: #333333;">}</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(!</span>keep<span style="color: #333333;">)</span>
<span style="color: #008800; font-weight: bold;">break</span><span style="color: #333333;">;</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span></pre>
</div>
<br />
<span style="font-family: inherit; line-height: 115%;">The code above searches for vendor IDs 1027 or 9025 – the vendor ID’s associated to FTDI or Arduino. The vendor ID equal to 9025 is the more popular and more common value based on other articles in the internet, but mine has an ID of 1027. The easiest way to know is to just print the vendor IDs detected by the Android device. If the vendor ID matches the expected ID for our device, we will call the </span><span style="font-family: "courier new"; line-height: 115%;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;">requestPermission()</span></span><span style="font-family: inherit; line-height: 115%;"> method. With this, the intent will be broadcasted and picked up by our receiver, starting and opening the connection.</span><br />
<span style="font-family: inherit;"><br />
</span> <span style="font-family: inherit;">Once communication is opened, we can start sending and receiving data. To receive from Arduino, simply add the codes below. Note that we are appending the data received to the text view.</span><br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">private</span> UsbSerialInterface<span style="color: #333333;">.</span><span style="color: #0000cc;">UsbReadCallback</span> mCallback <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">new</span> UsbSerialInterface<span style="color: #333333;">.</span><span style="color: #0000cc;">UsbReadCallback</span><span style="color: #333333;">()</span> <span style="color: #333333;">{</span>
<span style="color: #888888;">//Defining a Callback which triggers whenever data is read.</span>
<span style="color: #555555; font-weight: bold;">@Override</span>
<span style="color: #008800; font-weight: bold;">public</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">onReceivedData</span><span style="color: #333333;">(</span><span style="color: #333399; font-weight: bold;">byte</span><span style="color: #333333;">[]</span> arg0<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
String data <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">null</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span> <span style="color: #333333;">{</span>
data <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">new</span> String<span style="color: #333333;">(</span>arg0<span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">"UTF-8"</span><span style="color: #333333;">);</span>
data<span style="color: #333333;">.</span><span style="color: #0000cc;">concat</span><span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"/n"</span><span style="color: #333333;">);</span>
tvAppend<span style="color: #333333;">(</span>displayView<span style="color: #333333;">,</span> data<span style="color: #333333;">);</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">catch</span> <span style="color: #333333;">(</span>UnsupportedEncodingException e<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
e<span style="color: #333333;">.</span><span style="color: #0000cc;">printStackTrace</span><span style="color: #333333;">();</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">};</span>
<span style="color: #008800; font-weight: bold;">private</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">tvAppend</span><span style="color: #333333;">(</span><span style="color: #008800; font-weight: bold;">final</span> TextView tv<span style="color: #333333;">,</span> <span style="color: #008800; font-weight: bold;">final</span> CharSequence text<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
runOnUiThread<span style="color: #333333;">(</span><span style="color: #008800; font-weight: bold;">new</span> Runnable<span style="color: #333333;">()</span> <span style="color: #333333;">{</span>
<span style="color: #555555; font-weight: bold;">@Override</span> <span style="color: #008800; font-weight: bold;">public</span> <span style="color: #333399; font-weight: bold;">void</span> run<span style="color: #333333;">()</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>text <span style="color: #333333;">!=</span> <span style="color: #008800; font-weight: bold;">null</span><span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
tv<span style="color: #333333;">.</span><span style="color: #0000cc;">append</span><span style="color: #333333;">(</span>text<span style="color: #333333;">);</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">});</span>
<span style="color: #333333;">}</span>
</pre>
</div>
<br />
<span style="font-family: inherit;">Sending data is easier. We only need to get user input from the text field, and send it to the connected device.</span><br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">public</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">onClickSend</span><span style="color: #333333;">(</span>View view<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
String textInput <span style="color: #333333;">=</span> inputView<span style="color: #333333;">.</span><span style="color: #0000cc;">getText</span><span style="color: #333333;">().</span><span style="color: #0000cc;">toString</span><span style="color: #333333;">();</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">write</span><span style="color: #333333;">(</span>textInput<span style="color: #333333;">.</span><span style="color: #0000cc;">getBytes</span><span style="color: #333333;">());</span>
<span style="color: #333333;">}</span>
</pre>
</div>
<br />
<span style="font-family: inherit;">To control the LED in Arduino, simply add the code below. You are free to change </span><span style="color: blue; font-family: "courier new" , "courier" , monospace;">TONLED </span><span style="font-family: inherit;">and </span><span style="color: blue; font-family: "courier new" , "courier" , monospace;">TOFFLED </span><span style="font-family: inherit;">to whatever names you want. Just don’t forget to adjust the Arduino code as well.</span><br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">public</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">onClickToggle</span><span style="color: #333333;">(</span>View view<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">(</span>isLedON <span style="color: #333333;">==</span> <span style="color: #008800; font-weight: bold;">false</span><span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
isLedON <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">true</span><span style="color: #333333;">;</span>
tvAppend<span style="color: #333333;">(</span>displayView<span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">"\nLED TURNED ON\n"</span><span style="color: #333333;">);</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">write</span><span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"TONLED"</span><span style="color: #333333;">.</span><span style="color: #0000cc;">getBytes</span><span style="color: #333333;">());</span>
<span style="color: #333333;">}</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #333333;">{</span>
isLedON <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">false</span><span style="color: #333333;">;</span>
serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">write</span><span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"TOFFLED"</span><span style="color: #333333;">.</span><span style="color: #0000cc;">getBytes</span><span style="color: #333333;">());</span>
tvAppend<span style="color: #333333;">(</span>displayView<span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">"\nLED TURNED OFF\n"</span><span style="color: #333333;">);</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
</pre>
</div>
<br />
<span style="font-family: inherit;">You can close the connection using:</span><br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">serialPort<span style="color: #333333;">.</span><span style="color: #0000cc;">close</span><span style="color: #333333;">();</span>
</pre>
</div>
<span style="font-family: inherit;"><br />
</span> <span style="font-family: inherit;">We are almost done. In your manifest file, add the following so that your application will be notified of an attached USB device. </span><br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #557799;"><?xml version="1.0" encoding="utf-8"?></span>
<span style="color: #007700;"><manifest</span> <span style="color: #0000cc;">xmlns:android=</span><span style="background-color: #fff0f0;">"http://schemas.android.com/apk/res/android"</span>
<span style="color: #0000cc;">package=</span><span style="background-color: #fff0f0;">"yourpackage.com.name"</span><span style="color: #007700;">></span>
<span style="color: #007700;"><uses-feature</span> <span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">"android.hardware.usb.host"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"><application</span>
<span style="color: #0000cc;">android:allowBackup=</span><span style="background-color: #fff0f0;">"true"</span>
<span style="color: #0000cc;">android:icon=</span><span style="background-color: #fff0f0;">"@mipmap/ic_launcher"</span>
<span style="color: #0000cc;">android:label=</span><span style="background-color: #fff0f0;">"@string/app_name"</span>
<span style="color: #0000cc;">android:supportsRtl=</span><span style="background-color: #fff0f0;">"true"</span>
<span style="color: #0000cc;">android:theme=</span><span style="background-color: #fff0f0;">"@style/AppTheme"</span><span style="color: #007700;">></span>
<span style="color: #007700;"><activity</span>
<span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">".MainActivity"</span>
<span style="color: #0000cc;">android:label=</span><span style="background-color: #fff0f0;">"@string/app_name"</span>
<span style="color: #0000cc;">android:theme=</span><span style="background-color: #fff0f0;">"@style/AppTheme.NoActionBar"</span><span style="color: #007700;">></span>
<span style="color: #007700;"><intent-filter></span>
<span style="color: #007700;"><action</span> <span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">"android.intent.action.MAIN"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"><category</span> <span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">"android.intent.category.LAUNCHER"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"></intent-filter></span>
<span style="color: #007700;"><intent-filter></span>
<span style="color: #007700;"><action</span> <span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">"android.hardware.usb.action.USB_DEVICE_ATTACHED"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"></intent-filter></span>
<span style="color: #007700;"><meta-data</span>
<span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">"android.hardware.usb.action.USB_DEVICE_ATTACHED"</span>
<span style="color: #0000cc;">android:resource=</span><span style="background-color: #fff0f0;">"@xml/device_filter"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"><intent-filter></span>
<span style="color: #007700;"><action</span> <span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">"android.hardware.usb.action.USB_DEVICE_DETACHED"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"></intent-filter></span>
<span style="color: #007700;"></activity></span>
<span style="color: #007700;"></application></span>
<span style="color: #007700;"></manifest></span>
</pre>
</div>
<br />
<span style="font-family: inherit; line-height: 107%;">Create an xml folder inside the res folder and add device_filter.xml</span><br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #557799;"><?xml version="1.0" encoding="utf-8"?></span>
<span style="color: #007700;"><resources></span>
<span style="color: #007700;"><usb-device</span>
<span style="color: #0000cc;">vendor-id=</span><span style="background-color: #fff0f0;">"9025"</span><span style="color: #007700;">/></span>
<span style="color: #007700;"></resources></span>
</pre>
</div>
<br />
<span style="font-family: inherit; line-height: 107%;">And… were done! Additional tips, we can add a checker to confirm that the serial connection is already open. This saves us from crashes due to attempts to send serial data while the connection is still closed. We can also add clear buttons, or place the text view inside a scroll view then automatically scroll to end of page using: </span><br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mScrollView<span style="color: #333333;">.</span><span style="color: #0000cc;">smoothScrollTo</span><span style="color: #333333;">(</span><span style="color: #0000dd; font-weight: bold;">0</span><span style="color: #333333;">,</span> displayView<span style="color: #333333;">.</span><span style="color: #0000cc;">getBottom</span><span style="color: #333333;">());</span>
</pre>
</div>
<br />
<span style="font-family: inherit;">That’s it. If you want to extend your phone’s sensors, or if you want to add storage, wireless and messaging capability, camera and orientation sensors in your microprocessor project with just one device, USB On-the-Go, may be your way to go.</span><br />
<span style="font-family: inherit;"><br />
</span><span style="font-family: inherit;"> A demo application, SimpleArDroid by <a href="https://play.google.com/store/apps/developer?id=YMSoftLabs">YMSoftLabs</a> can be downloaded from Google Play. Here's a video of how the system works.</span><br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="226" src="https://www.youtube.com/embed/4byBMpiuuZI" width="400"></iframe><br /></div>
<div style="text-align: center;">
<br /></div>
<span style="font-family: inherit;"><br />
</span> <span style="font-family: inherit;">References:</span><br />
<span style="font-family: inherit;"><a href="https://felhr85.net/2014/11/11/usbserial-a-serial-port-driver-library-for-android-v2-0/">UsbSerial: A serial port driver library for Android v3.0</a></span><br />
<span style="font-family: inherit;"><a href="https://github.com/felHR85/UsbSerial/releases">USBSerial</a></span><br />
<span style="font-family: inherit;"><a href="http://www.allaboutcircuits.com/projects/communicate-with-your-arduino-through-android/">Communicate with Your Arduino Through Android</a></span><br />
<br />
<div>
<br /></div>
'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com71tag:blogger.com,1999:blog-3967613250975275925.post-74046298489985072662016-02-13T18:26:00.001+08:002016-02-13T18:26:46.089+08:00Raspberry Pi 2 N6100 LCD (part 2)<br />
Raspberry Pi 2 playing video (mpg) on <a href="http://e-gizmo.com/KIT/COLOR%20LCD%20SHIELD.html">Nokia 6100 LCD</a>.<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/QcnIpFxbtLw/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/QcnIpFxbtLw?feature=player_embedded" width="320"></iframe></div>
<br />
github: <a href="https://github.com/julznc/rpi-n6100lcd">rpi-n6100lcd</a><br />
<br />
Reference:<br />
<a href="https://github.com/phamquy/FFmpeg-tutorial-samples/">FFmpeg-tutorial-samples</a><br />
<a href="http://projectproto.blogspot.com/2016/02/raspberry-pi-2-n6100-lcd.html">N6100LCD (part 1)</a> 'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com1tag:blogger.com,1999:blog-3967613250975275925.post-53289757335764851522016-02-08T16:47:00.003+08:002016-02-08T18:45:46.370+08:00Raspberry Pi 2 N6100 LCD<span id="goog_1713483510"></span><span id="goog_1713483511"></span><br />
<a href="https://www.raspberrypi.org/products/raspberry-pi-2-model-b/" target="_blank">Raspberry PI 2</a> and <a href="http://e-gizmo.com/KIT/COLOR%20LCD%20SHIELD.html" target="_blank">Nokia 6100 LCD</a> (9-bit SPI interface).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpyrY5MxcwTOpPms6-l0-5QETo_N0uSzGm3_yI-aHir5fuycGCaXVb0hL_Owsx7IR3SDGrpG-NrDsRGdxgiU6FIAah6niXaT7PYfQUZ6ND8TEu9vjbNdTILFynMVk_J0S5DSazhxS_pYku/s1600/rpi2-n6100lcd-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpyrY5MxcwTOpPms6-l0-5QETo_N0uSzGm3_yI-aHir5fuycGCaXVb0hL_Owsx7IR3SDGrpG-NrDsRGdxgiU6FIAah6niXaT7PYfQUZ6ND8TEu9vjbNdTILFynMVk_J0S5DSazhxS_pYku/s320/rpi2-n6100lcd-2.jpg" width="320" /></a></div>
<span id="goog_1713483510"><todo: code="" insert=""></todo:></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8DMEKbNKS5cF7-FBat9sN8s_WgIRJBygUhD5vnG-uG9Hz5eDF8H6zY_9u_9f_LYDwP0g1vjI-jx8LX-0gXLyC7Iw8gt2TsdmUB8zdsrr7FqRM8I7FU9uF8M8FZyfYckLICX1fo3VCO27C/s1600/rpi2-n6100lcd.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8DMEKbNKS5cF7-FBat9sN8s_WgIRJBygUhD5vnG-uG9Hz5eDF8H6zY_9u_9f_LYDwP0g1vjI-jx8LX-0gXLyC7Iw8gt2TsdmUB8zdsrr7FqRM8I7FU9uF8M8FZyfYckLICX1fo3VCO27C/s320/rpi2-n6100lcd.jpg" width="320" /></a></div>
<br />
<br />
<span id="goog_1713483510">References:</span><br />
<span id="goog_1713483510"><a href="https://github.com/R42/pinokia" target="_blank">R42/pinoki</a> </span><br />
<span id="goog_1713483510"><a href="http://e-gizmo.com/KIT/COLOR%20LCD%20SHIELD.html" target="_blank"><span class="style12 style15">e-Gizmo Color LCD Shield</span></a></span><br />
<span id="goog_1713483510"><span class="style12 style15"><a href="https://github.com/msperl/spi-bcm2835" target="_blank">r-pi 2 spi driver with (9-bit spi support)</a></span></span><br />
<span id="goog_1713483510"><span class="style12 style15"><a href="http://zarb.org/~gc/html/libpng.html" target="_blank">libpng example program</a></span></span><span id="goog_1713483510"><span class="style12 style15"> (<i>to load PNG image</i>) </span></span><br />
<span id="goog_1713483510"><span class="style12 style15"><a href="https://botmayank.wordpress.com/2014/06/24/running-the-nokia-6610-lcd-with-a-raspberry-pi/" target="_blank">N6610 LCD with a Raspberry Pi</a> </span></span><br />
<span id="goog_1713483510"><span class="style12 style15"><a href="https://www.raspberrypi.org/downloads/raspbian/" target="_blank">Rasbian download</a> </span></span><br />
<span id="goog_1713483510"><span class="style12 style15"><a href="http://pinout.xyz/">R-Pi pinout</a> </span></span><br />
<span id="goog_1713483510"><span class="style12 style15"> </span> </span>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com2tag:blogger.com,1999:blog-3967613250975275925.post-7311004515005431932016-01-09T19:05:00.000+08:002016-01-10T21:30:18.139+08:00Intel Edison: LED BlinkerHere's a "hello world" test application for <a href="http://www.intel.com/content/www/us/en/do-it-yourself/edison.html" target="_blank">Intel® Edison Compute Module</a>. As what the title says, it's just a simple LED blinker task executed by a fast processor. <img alt="" src="data:image/gif;base64,R0lGODlhEgASANUiAKuCNP///5mZ/+ioKszM//XZUPj2cZttbMz//3d3d66goDNmzLKysqyPjoJ8fJkzM/vwvDOZzImJycxmZpKSkoZSUpiSkvvxvmYzM72DLoBgJsyZMzMAZuWqLemsLbF5PUh84+26WgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQF9AEiACwAAAAAEgASAEAGnECRcEgsEg8MQSCgZAYQAgQiojGKANis9Tq4FAwcA9hQKAwAQ8AAw3A6oYTEwFHEQpaQPLZ4OFgaDQqCgoB9BxVCGUgCEhILj48SSgloaQMfEw+aDxMUc1tXWXtbagFkX2VmlUJqXmKvr2VnQosEBAK2uLe2EYgifrhuSnACVIkgDATCT0oCCXSsaxNNSnFy0ERYAwNlHh2joOEiQQAh+QQFDwAiACwFAAQACAACAEAGDkCRKEAkiigbSiiE3AQBACH5BAUyACIALAUABAAIAAIAQAYLQJGIYzAQRcVkMggAIfkEBQ8AIgAsBQAEAAgAAgBABg5AkShAJIooG0oohNwEAQAh+QQF9AEiACwFAAQACAACAEAGC0CRiGMwEEXFZDIIADs=" /><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dx_uOYYiACM-K8lx6T1yQOdbsbS_w4QCD_9g9E_ibeKH2eLfx-AdQEveIP2dpTpLk3MYOvuenXGcdLW6d9-nQ' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
Below is the tiny module powered by Intel Atom dual-core processor at 500 MHz, with 1 GB DDR3 RAM, 4 GB eMMC Flash, Bluetooth 4.0 and Wi-Fi. It runs <a href="https://www.yoctoproject.org/tools-resources/projects/poky" target="_blank">Yocto Linux</a> (Linux 3.10.17-poky i686).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO_n6ULESuIEKgYeOJrSePW-7a_M0sCO0ZKlJgBWOXgR2KTsJfsJIY0qVZFGEtA2zhc7dxjCwzdvxCmtmNRs43lSLdp_WevPUClfy_zOaZ35qwNv08zEYPfS_ATi8UmJz_2cBe_fy5e_0I/s1600/IMG_20160109_153114.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO_n6ULESuIEKgYeOJrSePW-7a_M0sCO0ZKlJgBWOXgR2KTsJfsJIY0qVZFGEtA2zhc7dxjCwzdvxCmtmNRs43lSLdp_WevPUClfy_zOaZ35qwNv08zEYPfS_ATi8UmJz_2cBe_fy5e_0I/s320/IMG_20160109_153114.jpg" width="320" /></a></div>
<br />
Some Intel Edison breakout boards that are shield-like (can be stacked on each other) are also already available on <a href="https://www.sparkfun.com/categories/272" target="_blank">SparkFun</a>. Most useful one is the <a href="https://www.sparkfun.com/products/13045" target="_blank">base block</a> which is used for connecting the Edison module to the host PC via USB. This block has two mini USB ports. The first port is an OTG type and is primarily used for flashing firmware/image of the Edison. The other one is an FTDI-based USB-to-Serial which is used for connecting to a host's serial terminal/console.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3wOi7_aKnubfbR7WlIQXqFZz7C8Bt1qV9-o-_aGbbVfi7o4_cpYhRL_Qb1xXmXjgdyxgj8Qu991h_LzZu6oBti_01ZY-g9OF7LZo_-b_09yAjEvGeAvuh4klwOUu83DRa2zRdIgpB9fFR/s1600/IMG_20160109_152530.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3wOi7_aKnubfbR7WlIQXqFZz7C8Bt1qV9-o-_aGbbVfi7o4_cpYhRL_Qb1xXmXjgdyxgj8Qu991h_LzZu6oBti_01ZY-g9OF7LZo_-b_09yAjEvGeAvuh4klwOUu83DRa2zRdIgpB9fFR/s320/IMG_20160109_152530.jpg" width="320" /></a></div>
<br />
Initial configuration requires the Edison module to be connected to a serial terminal, like <a href="http://www.putty.org/" target="_blank">putty</a> (<i>sample <a href="http://pastebin.com/raw/WbG93v2t" target="_blank">boot log</a></i>). After configuring the <a href="https://software.intel.com/en-us/get-started-edison-windows-step4" target="_blank">WiFi</a> and the root's password, it is now possible to access the module remotely using <a href="https://software.intel.com/en-us/creating-an-ssh-connection-in-eclipse" target="_blank"><b>ssh</b> connection</a>, just like in the demo video above.<br />
<br />
The code below is a simple C++ code for blinking an LED connected at GP14. The code depends on <a href="http://iotdk.intel.com/docs/master/mraa/" target="_blank">mraa</a> low level library to access the GPIO hardware.<br />
<div style="background: #f8f8f8; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-style: italic;">/* intel edison led blink - yus 20150109 */</span>
<span style="color: #008800;">#include <mraa.hpp></span>
<span style="color: #008800;">#include <iostream></span>
<span style="color: #00bb00; font-weight: bold;">int</span> <span style="color: #00a000;">main</span>()
{
mraa<span style="color: #666666;">::</span>Gpio <span style="color: #666666;">*</span>gpio <span style="color: #666666;">=</span> <span style="color: #aa22ff; font-weight: bold;">new</span> mraa<span style="color: #666666;">::</span>Gpio( <span style="color: #666666;">36</span> <span style="color: #008800; font-style: italic;">/*=GP14!*/</span> );
<span style="color: #aa22ff; font-weight: bold;">if</span> (gpio <span style="color: #666666;">&&</span> gpio<span style="color: #666666;">-></span>dir(mraa<span style="color: #666666;">::</span>DIR_OUT)<span style="color: #666666;">==</span>mraa<span style="color: #666666;">::</span>SUCCESS)
{
std<span style="color: #666666;">::</span>cout<span style="color: #666666;"><<</span><span style="color: #bb4444;">"Blinking GP14. Press [CTRL+C] to stop...</span><span style="color: #bb6622; font-weight: bold;">\n</span><span style="color: #bb4444;">"</span>;
<span style="color: #aa22ff; font-weight: bold;">while</span> (<span style="color: #666666;">1</span>) {
gpio<span style="color: #666666;">-></span>write(<span style="color: #666666;">1</span>);
sleep(<span style="color: #666666;">1</span>);
gpio<span style="color: #666666;">-></span>write(<span style="color: #666666;">0</span>);
sleep(<span style="color: #666666;">1</span>);
}
}
<span style="color: #aa22ff; font-weight: bold;">return</span> <span style="color: #666666;">-1</span>;
}
</pre>
</div>
<br />
The provided Yocto Linux installed in the Edison already includes a GNU toolchain (GCC 4.9). So the demo code can be compiled/build inside the Edison itself.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1uCYQz9_luvIJC9y1Pif8Gcmceoxkd03NZ8tnUrTeb6iv34qDwmkVsRIkXSDF4qhG5TBDoBV0eQO42PGHS9WizvCbyvuHYDAIU4jnWon2RyxncQhgoUfg27LwzMd5MExXfT2hEQYXJiJt/s1600/putty.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1uCYQz9_luvIJC9y1Pif8Gcmceoxkd03NZ8tnUrTeb6iv34qDwmkVsRIkXSDF4qhG5TBDoBV0eQO42PGHS9WizvCbyvuHYDAIU4jnWon2RyxncQhgoUfg27LwzMd5MExXfT2hEQYXJiJt/s320/putty.png" width="320" /></a></div>
<br />
Alternatively, a <a href="https://www.youtube.com/watch?v=cKA2gx4JgSY" target="_blank">BASH script</a> can be also used to do a LED blink task.<br />
<div style="background: #f8f8f8; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-style: italic;">#!/bin/bash</span>
<span style="color: #008800; font-style: italic;"># select led pin</span>
<span style="color: darkgoldenrod;">pin</span><span style="color: #666666;">=</span>14
<span style="color: darkgoldenrod;">gpio</span><span style="color: #666666;">=</span>/sys/class/gpio/gpio<span style="color: darkgoldenrod;">$pin</span>
<span style="color: #aa22ff; font-weight: bold;">if</span> <span style="color: #666666;">[</span> ! -d <span style="color: #bb4444;">"$gpio"</span> <span style="color: #666666;">]</span>; <span style="color: #aa22ff; font-weight: bold;">then</span>
<span style="color: #aa22ff; font-weight: bold;"> </span><span style="color: #aa22ff;">echo</span> <span style="color: darkgoldenrod;">$pin</span> > /sys/class/gpio/export
<span style="color: #aa22ff; font-weight: bold;">fi</span>
<span style="color: #aa22ff;">echo </span>out > <span style="color: darkgoldenrod;">$gpio</span>/direction
<span style="color: #aa22ff;">echo </span>Blinking GP<span style="color: darkgoldenrod;">$pin</span>. Press <span style="color: #666666;">[</span>CTRL+C<span style="color: #666666;">]</span> to stop...
<span style="color: #aa22ff; font-weight: bold;">while</span> :
<span style="color: #aa22ff; font-weight: bold;">do</span>
<span style="color: #aa22ff; font-weight: bold;"> </span><span style="color: #aa22ff;">echo </span>1 > <span style="color: darkgoldenrod;">$gpio</span>/value
sleep 1
<span style="color: #aa22ff;">echo </span>0 > <span style="color: darkgoldenrod;">$gpio</span>/value
sleep 1
<span style="color: #aa22ff; font-weight: bold;">done</span>
</pre>
</div>
<br />
Also, for those who are comfortable developing with Arduino IDE, the Arduino IDE also <a href="https://software.intel.com/en-us/get-started-arduino-blink" target="_blank">supports</a> Intel Edison. However, you need to check the correct pin mappings if you're going to use boards other than Arduino's <a href="https://www.arduino.cc/en/ArduinoCertified/IntelEdison#toc3" target="_blank">Edison kit</a> or <a href="https://www.arduino.cc/en/ArduinoCertified/IntelEdison#toc4" target="_blank">Edison breakout board</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSnO1ZZHuvSIGxfoJpxKE3jmq3qBIQGsH__QIbEgn7MD9D-uhBqt9LEYhy_0rgWPXzs8qoHzElhOO8GnumFS7V4tpXIYmhZgjnXotEMeHI781Xr4O5eBOpR79U6Cb3_O6RDnD26LWb_mxy/s1600/arduino.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSnO1ZZHuvSIGxfoJpxKE3jmq3qBIQGsH__QIbEgn7MD9D-uhBqt9LEYhy_0rgWPXzs8qoHzElhOO8GnumFS7V4tpXIYmhZgjnXotEMeHI781Xr4O5eBOpR79U6Cb3_O6RDnD26LWb_mxy/s320/arduino.png" width="315" /></a></div>
<br />
<br />
References:<br />
<a href="https://software.intel.com/en-us/iot/library/edison-getting-started" target="_blank">Edison Getting Started</a><br />
<a href="https://learn.sparkfun.com/tutorials/sparkfun-blocks-for-intel-edison---gpio-block" target="_blank">Edison GPIO block</a><br />
<a href="https://software.intel.com/en-us/flashing-firmware-with-flash-tool-lite" target="_blank">Flashing Firmware</a><br />
<a href="http://iotdk.intel.com/docs/master/mraa/edison.html" target="_blank">mraa low level library</a> <br />
<br />'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com7tag:blogger.com,1999:blog-3967613250975275925.post-32481516150031950182015-09-12T20:36:00.005+08:002015-09-12T21:49:38.250+08:00PyOpenGL demo: Android Orientation<br />
<a href="https://github.com/julznc/pyopengl-demo-android-orientation" target="_blank">github/pyopengl-demo-android-orientation</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF7sq1pmzn-lud_S-Gko03WsJLYeOv18IbuOgSh3VI9EomRmga0PZAFu8dh9ROfXf41XWvDNfVRbh_CNIX8kIFwIPrrquiJJbihkcLlleD4UACcWooyQLHV_sLVtn8uk3FOnuVwGZgVOSM/s1600/IMG_20150912_214311.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF7sq1pmzn-lud_S-Gko03WsJLYeOv18IbuOgSh3VI9EomRmga0PZAFu8dh9ROfXf41XWvDNfVRbh_CNIX8kIFwIPrrquiJJbihkcLlleD4UACcWooyQLHV_sLVtn8uk3FOnuVwGZgVOSM/s320/IMG_20150912_214311.jpg" width="320" /></a></div>
<br />
<br />
<script src="http://gist-it.appspot.com/github/julznc/pyopengl-demo-android-orientation/blob/master/pyopengl_httpserver.py?"></script><br />
<br />
<script src="http://gist-it.appspot.com/github/julznc/pyopengl-demo-android-orientation/blob/master/sensor_httpclient.py"></script><br />
<br />'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com2tag:blogger.com,1999:blog-3967613250975275925.post-69565328004454588792015-06-14T19:21:00.002+08:002015-06-14T19:23:27.776+08:00Bluetooth Joystick Updated To v2.1<br />
Android <a href="http://projectproto.blogspot.com/2012/02/bluetooth-joystick.html" target="_blank">Bluetooth Dual-Joystick</a> App is now available on <a href="https://play.google.com/store/apps/details?id=com.ymsoftlabs.btjoystick" target="_blank">Google Play</a>.<br />
<br />
<br />
<br />'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com1tag:blogger.com,1999:blog-3967613250975275925.post-62287976239801372962014-11-30T14:33:00.001+08:002014-12-01T17:50:51.425+08:00AVR32 Stepper MotorAT32UC3L0128 and L293D interfaced with bipolar (4-wire) stepper motors...<br />
<br />
<iframe width="450" height="320" src="//www.youtube.com/embed/YaQX370s1hM" frameborder="0" allowfullscreen></iframe><br />
<br />
<div id="fb-root"></div><script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script><br />
<div class="fb-share-button" data-type="button_count" style="margin-bottom: 20px;"></div><br />
<br />
'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com0tag:blogger.com,1999:blog-3967613250975275925.post-38595269862612061792014-07-24T15:05:00.000+08:002014-07-27T12:47:01.677+08:00OpenCV Python: 2048 Game SolverA sample application of <a href="http://projectproto.blogspot.com/2014/07/opencv-python-digit-recognition.html" target="_blank">Digit Recognition.</a><br />
2048 solver algorithm based on <a href="http://diaryofatinker.blogspot.com/2014/03/an-artificial-intelligence-for-2048-game.html" target="_blank">term2048-AI</a><br />
<br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; height: 480px; overflow: auto; padding: .2em .6em; width: auto;"><pre style="line-height: 125%; margin: 0;"><span style="color: #007020; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">cv2</span>
<span style="color: #007020; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">numpy</span> <span style="color: #007020; font-weight: bold;">as</span> <span style="color: #0e84b5; font-weight: bold;">np</span>
<span style="color: #007020; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">win32api</span><span style="color: #666666;">,</span> <span style="color: #0e84b5; font-weight: bold;">win32gui</span><span style="color: #666666;">,</span> <span style="color: #0e84b5; font-weight: bold;">win32ui</span><span style="color: #666666;">,</span> <span style="color: #0e84b5; font-weight: bold;">win32con</span><span style="color: #666666;">,</span> <span style="color: #0e84b5; font-weight: bold;">win32com.client</span>
<span style="color: #007020; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">PIL</span> <span style="color: #007020; font-weight: bold;">import</span> Image, ImageFont, ImageDraw, ImageOps
<span style="color: #60a0b0; font-style: italic;"># create training model based on the given TTF font file</span>
<span style="color: #60a0b0; font-style: italic;"># http://projectproto.blogspot.com/2014/07/opencv-python-digit-recognition.html</span>
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">createDigitsModel</span>(fontfile, digitheight):
font <span style="color: #666666;">=</span> ImageFont<span style="color: #666666;">.</span>truetype(fontfile, digitheight)
samples <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>empty((<span style="color: #40a070;">0</span>,digitheight<span style="color: #666666;">*</span>(digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>)))
responses <span style="color: #666666;">=</span> []
<span style="color: #007020; font-weight: bold;">for</span> n <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">10</span>):
pil_im <span style="color: #666666;">=</span> Image<span style="color: #666666;">.</span>new(<span style="color: #4070a0;">"RGB"</span>, (digitheight, digitheight<span style="color: #666666;">*</span><span style="color: #40a070;">2</span>))
ImageDraw<span style="color: #666666;">.</span>Draw(pil_im)<span style="color: #666666;">.</span>text((<span style="color: #40a070;">0</span>, <span style="color: #40a070;">0</span>), <span style="color: #007020;">str</span>(n), font<span style="color: #666666;">=</span>font)
pil_im <span style="color: #666666;">=</span> pil_im<span style="color: #666666;">.</span>crop(pil_im<span style="color: #666666;">.</span>getbbox())
pil_im <span style="color: #666666;">=</span> ImageOps<span style="color: #666666;">.</span>invert(pil_im)
<span style="color: #60a0b0; font-style: italic;">#pil_im.save(str(n) + ".png")</span>
<span style="color: #60a0b0; font-style: italic;"># convert to cv image</span>
cv_image <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(np<span style="color: #666666;">.</span>array( pil_im ), cv2<span style="color: #666666;">.</span>COLOR_RGBA2BGRA)
gray <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(cv_image, cv2<span style="color: #666666;">.</span>COLOR_BGR2GRAY)
blur <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>GaussianBlur(gray,(<span style="color: #40a070;">5</span>,<span style="color: #40a070;">5</span>),<span style="color: #40a070;">0</span>)
thresh <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>adaptiveThreshold(blur,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">11</span>,<span style="color: #40a070;">2</span>)
roi <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>resize(thresh,(digitheight,digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>))
responses<span style="color: #666666;">.</span>append( n )
sample <span style="color: #666666;">=</span> roi<span style="color: #666666;">.</span>reshape((<span style="color: #40a070;">1</span>,digitheight<span style="color: #666666;">*</span>(digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>)))
samples <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>append(samples,sample,<span style="color: #40a070;">0</span>)
samples <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>array(samples,np<span style="color: #666666;">.</span>float32)
responses <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>array(responses,np<span style="color: #666666;">.</span>float32)
model <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>KNearest()
model<span style="color: #666666;">.</span>train(samples,responses)
<span style="color: #007020; font-weight: bold;">return</span> model
<span style="color: #007020; font-weight: bold;">class</span> <span style="color: #0e84b5; font-weight: bold;">Board</span>(<span style="color: #007020;">object</span>):
UP, DOWN, LEFT, RIGHT <span style="color: #666666;">=</span> <span style="color: #40a070;">1</span>, <span style="color: #40a070;">2</span>, <span style="color: #40a070;">3</span>, <span style="color: #40a070;">4</span>
FONT <span style="color: #666666;">=</span> <span style="color: #4070a0;">"font/ClearSans-Bold.ttf"</span>
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">__init__</span>(<span style="color: #007020;">self</span>, clientwindowtitle):
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>hwnd <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getClientWindow(clientwindowtitle)
<span style="color: #007020; font-weight: bold;">if</span> <span style="color: #007020; font-weight: bold;">not</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>hwnd:
<span style="color: #007020; font-weight: bold;">return</span>
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>hwndDC <span style="color: #666666;">=</span> win32gui<span style="color: #666666;">.</span>GetWindowDC(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>hwnd)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>mfcDC <span style="color: #666666;">=</span> win32ui<span style="color: #666666;">.</span>CreateDCFromHandle(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>hwndDC)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveDC <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>mfcDC<span style="color: #666666;">.</span>CreateCompatibleDC()
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>cl, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>ct, right, bot <span style="color: #666666;">=</span> win32gui<span style="color: #666666;">.</span>GetClientRect(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>hwnd)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>cw, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>ch <span style="color: #666666;">=</span> right<span style="color: #666666;">-</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>cl, bot<span style="color: #666666;">-</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>ct
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>cl <span style="color: #666666;">+=</span> win32api<span style="color: #666666;">.</span>GetSystemMetrics(win32con<span style="color: #666666;">.</span>SM_CXSIZEFRAME)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>ct <span style="color: #666666;">+=</span> win32api<span style="color: #666666;">.</span>GetSystemMetrics(win32con<span style="color: #666666;">.</span>SM_CYSIZEFRAME)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>ct <span style="color: #666666;">+=</span> win32api<span style="color: #666666;">.</span>GetSystemMetrics(win32con<span style="color: #666666;">.</span>SM_CYCAPTION)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>ch <span style="color: #666666;">+=</span> win32api<span style="color: #666666;">.</span>GetSystemMetrics(win32con<span style="color: #666666;">.</span>SM_CYSIZEFRAME)<span style="color: #666666;">*</span><span style="color: #40a070;">2</span>
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveBitMap <span style="color: #666666;">=</span> win32ui<span style="color: #666666;">.</span>CreateBitmap()
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveBitMap<span style="color: #666666;">.</span>CreateCompatibleBitmap(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>mfcDC, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>cw, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>ch)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveDC<span style="color: #666666;">.</span>SelectObject(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveBitMap)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>tiles, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>tileheight, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>contour <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>findTiles(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>getClientFrame())
<span style="color: #007020; font-weight: bold;">if</span> <span style="color: #007020; font-weight: bold;">not</span> <span style="color: #007020;">len</span>(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>tiles):
<span style="color: #007020; font-weight: bold;">return</span>
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>digitheight <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>tileheight <span style="color: #666666;">/</span> <span style="color: #40a070;">2</span>
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>digitsmodel <span style="color: #666666;">=</span> createDigitsModel(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>FONT, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>digitheight)
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>update()
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getClientWindow</span>(<span style="color: #007020;">self</span>, windowtitle):
toplist, winlist <span style="color: #666666;">=</span> [], []
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">enum_cb</span>(hwnd, results):
winlist<span style="color: #666666;">.</span>append((hwnd, win32gui<span style="color: #666666;">.</span>GetWindowText(hwnd)))
win32gui<span style="color: #666666;">.</span>EnumWindows(enum_cb, toplist)
window <span style="color: #666666;">=</span> [(hwnd, title) <span style="color: #007020; font-weight: bold;">for</span> hwnd, title <span style="color: #007020; font-weight: bold;">in</span> winlist <span style="color: #007020; font-weight: bold;">if</span> windowtitle<span style="color: #666666;">.</span>lower() <span style="color: #007020; font-weight: bold;">in</span> title<span style="color: #666666;">.</span>lower()]
<span style="color: #007020; font-weight: bold;">if</span> <span style="color: #007020; font-weight: bold;">not</span> <span style="color: #007020;">len</span>(window):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #40a070;">0</span>
<span style="color: #007020; font-weight: bold;">return</span> window[<span style="color: #40a070;">0</span>][<span style="color: #40a070;">0</span>]
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getClientFrame</span>(<span style="color: #007020;">self</span>):
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveDC<span style="color: #666666;">.</span>BitBlt((<span style="color: #40a070;">0</span>, <span style="color: #40a070;">0</span>), (<span style="color: #007020;">self</span><span style="color: #666666;">.</span>cw, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>ch),
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>mfcDC, (<span style="color: #007020;">self</span><span style="color: #666666;">.</span>cl, <span style="color: #007020;">self</span><span style="color: #666666;">.</span>ct), win32con<span style="color: #666666;">.</span>SRCCOPY)
bmpinfo <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveBitMap<span style="color: #666666;">.</span>GetInfo()
bmpstr <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>saveBitMap<span style="color: #666666;">.</span>GetBitmapBits(<span style="color: #007020;">True</span>)
pil_img <span style="color: #666666;">=</span> Image<span style="color: #666666;">.</span>frombuffer( <span style="color: #4070a0;">'RGB'</span>,
(bmpinfo[<span style="color: #4070a0;">'bmWidth'</span>], bmpinfo[<span style="color: #4070a0;">'bmHeight'</span>]),
bmpstr, <span style="color: #4070a0;">'raw'</span>, <span style="color: #4070a0;">'BGRX'</span>, <span style="color: #40a070;">0</span>, <span style="color: #40a070;">1</span>)
array <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>array( pil_img )
cvimage <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(array, cv2<span style="color: #666666;">.</span>COLOR_RGBA2BGRA)
<span style="color: #007020; font-weight: bold;">return</span> cvimage
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">findTiles</span>(<span style="color: #007020;">self</span>, cvframe):
tiles, avgh <span style="color: #666666;">=</span> [], <span style="color: #40a070;">0</span>
gray <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(cvframe,cv2<span style="color: #666666;">.</span>COLOR_BGRA2GRAY)
thresh <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>adaptiveThreshold(gray,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">11</span>,<span style="color: #40a070;">2</span>)
contours, hierarchy <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>findContours(thresh<span style="color: #666666;">.</span>copy(), cv2<span style="color: #666666;">.</span>RETR_TREE, cv2<span style="color: #666666;">.</span>CHAIN_APPROX_SIMPLE)
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">findBoard</span>(contours): <span style="color: #60a0b0; font-style: italic;"># get largest square</span>
ww, sqcnt <span style="color: #666666;">=</span> <span style="color: #40a070;">10</span>, <span style="color: #007020;">None</span>
<span style="color: #007020; font-weight: bold;">for</span> cnt <span style="color: #007020; font-weight: bold;">in</span> contours:
x,y,w,h <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>boundingRect(cnt)
<span style="color: #007020; font-weight: bold;">if</span> w<span style="color: #666666;">></span>ww <span style="color: #007020; font-weight: bold;">and</span> <span style="color: #007020;">abs</span>(w<span style="color: #666666;">-</span>h)<span style="color: #666666;"><</span>w<span style="color: #666666;">/</span><span style="color: #40a070;">10</span>:
ww <span style="color: #666666;">=</span> w
sqcnt <span style="color: #666666;">=</span> cnt
<span style="color: #007020; font-weight: bold;">return</span> sqcnt
board <span style="color: #666666;">=</span> findBoard(contours)
<span style="color: #007020; font-weight: bold;">if</span> board<span style="color: #666666;">==</span><span style="color: #007020;">None</span>:
<span style="color: #007020; font-weight: bold;">print</span> <span style="color: #4070a0;">'board not found!'</span>
<span style="color: #007020; font-weight: bold;">return</span> tiles, avgh, board
bx,by,bw,bh <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>boundingRect(board)
<span style="color: #60a0b0; font-style: italic;">#cv2.rectangle(cvframe,(bx,by),(bx+bw,by+bh),(0,255,0),2)</span>
<span style="color: #60a0b0; font-style: italic;">#cv2.imshow('board',cvframe)</span>
<span style="color: #60a0b0; font-style: italic;">#cv2.waitKey(0)</span>
<span style="color: #60a0b0; font-style: italic;">#cv2.destroyWindow( 'board' ) </span>
maxh <span style="color: #666666;">=</span> bh<span style="color: #666666;">/</span><span style="color: #40a070;">4</span>
minh <span style="color: #666666;">=</span> (maxh<span style="color: #666666;">*</span><span style="color: #40a070;">4</span>)<span style="color: #666666;">/</span><span style="color: #40a070;">5</span>
count <span style="color: #666666;">=</span> <span style="color: #40a070;">0</span>
<span style="color: #007020; font-weight: bold;">for</span> contour <span style="color: #007020; font-weight: bold;">in</span> contours:
x,y,w,h <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>boundingRect(contour)
<span style="color: #007020; font-weight: bold;">if</span> y<span style="color: #666666;">></span>by <span style="color: #007020; font-weight: bold;">and</span> w<span style="color: #666666;">></span>minh <span style="color: #007020; font-weight: bold;">and</span> w<span style="color: #666666;"><</span>maxh <span style="color: #007020; font-weight: bold;">and</span> h<span style="color: #666666;">></span>minh <span style="color: #007020; font-weight: bold;">and</span> h<span style="color: #666666;"><</span>maxh:
avgh <span style="color: #666666;">+=</span> h
count <span style="color: #666666;">+=</span> <span style="color: #40a070;">1</span>
<span style="color: #007020; font-weight: bold;">if</span> <span style="color: #007020; font-weight: bold;">not</span> count:
<span style="color: #007020; font-weight: bold;">print</span> <span style="color: #4070a0;">'no tile found!'</span>
<span style="color: #007020; font-weight: bold;">return</span> tiles, avgh, board
avgh <span style="color: #666666;">=</span> avgh <span style="color: #666666;">/</span> count
margin <span style="color: #666666;">=</span> (bh<span style="color: #666666;">-</span>avgh<span style="color: #666666;">*</span><span style="color: #40a070;">4</span>)<span style="color: #666666;">/</span><span style="color: #40a070;">5</span>
<span style="color: #007020; font-weight: bold;">for</span> row <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
<span style="color: #007020; font-weight: bold;">for</span> col <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
x0 <span style="color: #666666;">=</span> bx <span style="color: #666666;">+</span> avgh<span style="color: #666666;">*</span>col <span style="color: #666666;">+</span> margin<span style="color: #666666;">*</span>(col<span style="color: #666666;">+</span><span style="color: #40a070;">1</span>)
x1 <span style="color: #666666;">=</span> x0 <span style="color: #666666;">+</span> avgh
y0 <span style="color: #666666;">=</span> by <span style="color: #666666;">+</span> avgh<span style="color: #666666;">*</span>row <span style="color: #666666;">+</span> margin<span style="color: #666666;">*</span>(row<span style="color: #666666;">+</span><span style="color: #40a070;">1</span>)
y1 <span style="color: #666666;">=</span> y0 <span style="color: #666666;">+</span> avgh
tiles<span style="color: #666666;">.</span>append([x0, y0, x1, y1])
<span style="color: #60a0b0; font-style: italic;">#cv2.rectangle(cvframe,(x0,y0),(x1,y1),(0,255,0),2)</span>
<span style="color: #60a0b0; font-style: italic;">#cv2.imshow('tiles',cvframe)</span>
<span style="color: #60a0b0; font-style: italic;">#cv2.waitKey(0)</span>
<span style="color: #60a0b0; font-style: italic;">#cv2.destroyWindow( 'tiles' ) </span>
<span style="color: #007020; font-weight: bold;">return</span> tiles, avgh, board
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getTileThreshold</span>(<span style="color: #007020;">self</span>, tileimage):
gray <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(tileimage,cv2<span style="color: #666666;">.</span>COLOR_BGR2GRAY)
row, col <span style="color: #666666;">=</span> gray<span style="color: #666666;">.</span>shape
tmp <span style="color: #666666;">=</span> gray<span style="color: #666666;">.</span>copy()<span style="color: #666666;">.</span>reshape(<span style="color: #40a070;">1</span>, row<span style="color: #666666;">*</span>col)
counts <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>bincount(tmp[<span style="color: #40a070;">0</span>])
sort <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>sort(counts)
modes, freqs <span style="color: #666666;">=</span> [], []
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #007020;">len</span>(sort)):
freq <span style="color: #666666;">=</span> sort[<span style="color: #666666;">-</span><span style="color: #40a070;">1</span><span style="color: #666666;">-</span>i]
<span style="color: #007020; font-weight: bold;">if</span> freq <span style="color: #666666;"><</span> <span style="color: #40a070;">4</span>:
<span style="color: #007020; font-weight: bold;">break</span>
mode <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>where(counts<span style="color: #666666;">==</span>freq)[<span style="color: #40a070;">0</span>][<span style="color: #40a070;">0</span>]
modes<span style="color: #666666;">.</span>append(mode)
freqs<span style="color: #666666;">.</span>append(freq)
bg, fg <span style="color: #666666;">=</span> modes[<span style="color: #40a070;">0</span>], modes[<span style="color: #40a070;">0</span>]
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #007020;">len</span>(modes)):
fg <span style="color: #666666;">=</span> modes[i]
<span style="color: #60a0b0; font-style: italic;">#if abs(bg-fg)>=48:</span>
<span style="color: #007020; font-weight: bold;">if</span> <span style="color: #007020;">abs</span>(bg<span style="color: #666666;">-</span>fg)<span style="color: #666666;">></span><span style="color: #40a070;">32</span> <span style="color: #007020; font-weight: bold;">and</span> <span style="color: #007020;">abs</span>(fg<span style="color: #666666;">-</span><span style="color: #40a070;">150</span>)<span style="color: #666666;">></span><span style="color: #40a070;">4</span>: <span style="color: #60a0b0; font-style: italic;"># 150?!</span>
<span style="color: #007020; font-weight: bold;">break</span>
<span style="color: #60a0b0; font-style: italic;">#print bg, fg</span>
<span style="color: #007020; font-weight: bold;">if</span> bg<span style="color: #666666;">></span>fg: <span style="color: #60a0b0; font-style: italic;"># needs dark background ?</span>
tmp <span style="color: #666666;">=</span> <span style="color: #40a070;">255</span> <span style="color: #666666;">-</span> tmp
bg, fg <span style="color: #666666;">=</span> <span style="color: #40a070;">255</span><span style="color: #666666;">-</span>bg, <span style="color: #40a070;">255</span><span style="color: #666666;">-</span>fg
tmp <span style="color: #666666;">=</span> tmp<span style="color: #666666;">.</span>reshape(row, col)
ret, thresh <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>threshold(tmp,(bg<span style="color: #666666;">+</span>fg)<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>,<span style="color: #40a070;">255</span>,cv2<span style="color: #666666;">.</span>THRESH_BINARY)
<span style="color: #007020; font-weight: bold;">return</span> thresh
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getTileNumbers</span>(<span style="color: #007020;">self</span>, cvframe):
numbers <span style="color: #666666;">=</span> []
outframe <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>zeros(cvframe<span style="color: #666666;">.</span>shape,np<span style="color: #666666;">.</span>uint8)
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">guessNumber</span>(digits):
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">1</span>,<span style="color: #40a070;">16</span>):
nn <span style="color: #666666;">=</span> <span style="color: #40a070;">2</span><span style="color: #666666;">**</span>i
ss <span style="color: #666666;">=</span> <span style="color: #007020;">str</span>(nn)
dd <span style="color: #666666;">=</span> [<span style="color: #007020;">int</span>(c) <span style="color: #007020; font-weight: bold;">for</span> c <span style="color: #007020; font-weight: bold;">in</span> ss]
<span style="color: #007020; font-weight: bold;">if</span> <span style="color: #007020;">set</span>(digits) <span style="color: #666666;">==</span> <span style="color: #007020;">set</span>(dd):
<span style="color: #007020; font-weight: bold;">return</span> nn
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #40a070;">0</span>
<span style="color: #007020; font-weight: bold;">for</span> tile <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>tiles:
x0,y0,x1,y1 <span style="color: #666666;">=</span> tile
tileimage <span style="color: #666666;">=</span> cvframe[y0:y1,x0:x1]
cv2<span style="color: #666666;">.</span>rectangle(cvframe,(x0,y0),(x1,y1),(<span style="color: #40a070;">0</span>,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">0</span>),<span style="color: #40a070;">2</span>)
cv2<span style="color: #666666;">.</span>rectangle(outframe,(x0,y0),(x1,y1),(<span style="color: #40a070;">0</span>,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">0</span>),<span style="color: #40a070;">1</span>)
thresh <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getTileThreshold(tileimage)
contours,hierarchy <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>findContours(thresh<span style="color: #666666;">.</span>copy(),cv2<span style="color: #666666;">.</span>RETR_EXTERNAL,cv2<span style="color: #666666;">.</span>CHAIN_APPROX_SIMPLE)
dh <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>digitheight
digits <span style="color: #666666;">=</span> []
<span style="color: #007020; font-weight: bold;">for</span> cnt <span style="color: #007020; font-weight: bold;">in</span> contours:
x,y,w,h <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>boundingRect(cnt)
<span style="color: #007020; font-weight: bold;">if</span> h<span style="color: #666666;">></span>w <span style="color: #007020; font-weight: bold;">and</span> h<span style="color: #666666;">></span>(dh<span style="color: #666666;">*</span><span style="color: #40a070;">1</span>)<span style="color: #666666;">/</span><span style="color: #40a070;">5</span> <span style="color: #007020; font-weight: bold;">and</span> h<span style="color: #666666;"><</span>(dh<span style="color: #666666;">*</span><span style="color: #40a070;">6</span>)<span style="color: #666666;">/</span><span style="color: #40a070;">5</span>:
cv2<span style="color: #666666;">.</span>rectangle(cvframe,(x0<span style="color: #666666;">+</span>x,y0<span style="color: #666666;">+</span>y),(x0<span style="color: #666666;">+</span>x<span style="color: #666666;">+</span>w,y0<span style="color: #666666;">+</span>y<span style="color: #666666;">+</span>h),(<span style="color: #40a070;">0</span>,<span style="color: #40a070;">0</span>,<span style="color: #40a070;">255</span>),<span style="color: #40a070;">1</span>)
roi <span style="color: #666666;">=</span> thresh[y:y<span style="color: #666666;">+</span>h,x:x<span style="color: #666666;">+</span>w]
roi <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>resize(roi,(dh,dh<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>))
roi <span style="color: #666666;">=</span> roi<span style="color: #666666;">.</span>reshape((<span style="color: #40a070;">1</span>,dh<span style="color: #666666;">*</span>(dh<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>)))
roi <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>float32(roi)
retval, results, neigh_resp, dists <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>digitsmodel<span style="color: #666666;">.</span>find_nearest(roi, k<span style="color: #666666;">=</span><span style="color: #40a070;">1</span>)
digit <span style="color: #666666;">=</span> <span style="color: #007020;">int</span>((results[<span style="color: #40a070;">0</span>][<span style="color: #40a070;">0</span>]))
string <span style="color: #666666;">=</span> <span style="color: #007020;">str</span>(digit)
digits<span style="color: #666666;">.</span>append(digit)
cv2<span style="color: #666666;">.</span>putText(outframe,string,(x0<span style="color: #666666;">+</span>x,y0<span style="color: #666666;">+</span>y<span style="color: #666666;">+</span>h),<span style="color: #40a070;">0</span>,<span style="color: #007020;">float</span>(h)<span style="color: #666666;">/</span><span style="color: #40a070;">24</span>,(<span style="color: #40a070;">0</span>,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">0</span>))
numbers<span style="color: #666666;">.</span>append(guessNumber(digits))
<span style="color: #007020; font-weight: bold;">return</span> numbers, outframe
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getWindowHandle</span>(<span style="color: #007020;">self</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>hwnd
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getBoardContour</span>(<span style="color: #007020;">self</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>contour
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">update</span>(<span style="color: #007020;">self</span>):
frame <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getClientFrame()
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>tilenumbers, outframe <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getTileNumbers(frame)
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>tilenumbers, frame, outframe
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">copyTileNumbers</span>(<span style="color: #007020;">self</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>tilenumbers[:]
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getCell</span>(<span style="color: #007020;">self</span>, tiles, x, y):
<span style="color: #007020; font-weight: bold;">return</span> tiles[(y<span style="color: #666666;">*</span><span style="color: #40a070;">4</span>)<span style="color: #666666;">+</span>x]
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">setCell</span>(<span style="color: #007020;">self</span>, tiles, x, y, v):
tiles[(y<span style="color: #666666;">*</span><span style="color: #40a070;">4</span>)<span style="color: #666666;">+</span>x] <span style="color: #666666;">=</span> v
<span style="color: #007020; font-weight: bold;">return</span> tiles
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getCol</span>(<span style="color: #007020;">self</span>, tiles, x):
<span style="color: #007020; font-weight: bold;">return</span> [<span style="color: #007020;">self</span><span style="color: #666666;">.</span>getCell(tiles, x, i) <span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>)]
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">setCol</span>(<span style="color: #007020;">self</span>, tiles, x, col):
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>setCell(tiles, x, i, col[i])
<span style="color: #007020; font-weight: bold;">return</span> tiles
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">getLine</span>(<span style="color: #007020;">self</span>, tiles, y):
<span style="color: #007020; font-weight: bold;">return</span> [<span style="color: #007020;">self</span><span style="color: #666666;">.</span>getCell(tiles, i, y) <span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>)]
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">setLine</span>(<span style="color: #007020;">self</span>, tiles, y, line):
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>setCell(tiles, i, y, line[i])
<span style="color: #007020; font-weight: bold;">return</span> tiles
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">validMove</span>(<span style="color: #007020;">self</span>, tilenumbers, direction):
<span style="color: #007020; font-weight: bold;">if</span> direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>UP <span style="color: #007020; font-weight: bold;">or</span> direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>DOWN:
<span style="color: #007020; font-weight: bold;">for</span> x <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
col <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getCol(tilenumbers, x)
<span style="color: #007020; font-weight: bold;">for</span> y <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
<span style="color: #007020; font-weight: bold;">if</span>(y <span style="color: #666666;"><</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span> <span style="color: #007020; font-weight: bold;">and</span> col[y] <span style="color: #666666;">==</span> col[y<span style="color: #666666;">+</span><span style="color: #40a070;">1</span>] <span style="color: #007020; font-weight: bold;">and</span> col[y]<span style="color: #666666;">!=</span><span style="color: #40a070;">0</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">True</span>
<span style="color: #007020; font-weight: bold;">if</span>(direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>DOWN <span style="color: #007020; font-weight: bold;">and</span> y <span style="color: #666666;">></span> <span style="color: #40a070;">0</span> <span style="color: #007020; font-weight: bold;">and</span> col[y] <span style="color: #666666;">==</span> <span style="color: #40a070;">0</span> <span style="color: #007020; font-weight: bold;">and</span> col[y<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>]<span style="color: #666666;">!=</span><span style="color: #40a070;">0</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">True</span>
<span style="color: #007020; font-weight: bold;">if</span>(direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>UP <span style="color: #007020; font-weight: bold;">and</span> y <span style="color: #666666;"><</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span> <span style="color: #007020; font-weight: bold;">and</span> col[y] <span style="color: #666666;">==</span> <span style="color: #40a070;">0</span> <span style="color: #007020; font-weight: bold;">and</span> col[y<span style="color: #666666;">+</span><span style="color: #40a070;">1</span>]<span style="color: #666666;">!=</span><span style="color: #40a070;">0</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">True</span>
<span style="color: #007020; font-weight: bold;">if</span> direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>LEFT <span style="color: #007020; font-weight: bold;">or</span> direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>RIGHT:
<span style="color: #007020; font-weight: bold;">for</span> y <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
line <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getLine(tilenumbers, y)
<span style="color: #007020; font-weight: bold;">for</span> x <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
<span style="color: #007020; font-weight: bold;">if</span>(x <span style="color: #666666;"><</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span> <span style="color: #007020; font-weight: bold;">and</span> line[x] <span style="color: #666666;">==</span> line[x<span style="color: #666666;">+</span><span style="color: #40a070;">1</span>] <span style="color: #007020; font-weight: bold;">and</span> line[x]<span style="color: #666666;">!=</span><span style="color: #40a070;">0</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">True</span>
<span style="color: #007020; font-weight: bold;">if</span>(direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>RIGHT <span style="color: #007020; font-weight: bold;">and</span> x <span style="color: #666666;">></span> <span style="color: #40a070;">0</span> <span style="color: #007020; font-weight: bold;">and</span> line[x] <span style="color: #666666;">==</span> <span style="color: #40a070;">0</span> <span style="color: #007020; font-weight: bold;">and</span> line[x<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>]<span style="color: #666666;">!=</span><span style="color: #40a070;">0</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">True</span>
<span style="color: #007020; font-weight: bold;">if</span>(direction <span style="color: #666666;">==</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>LEFT <span style="color: #007020; font-weight: bold;">and</span> x <span style="color: #666666;"><</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span> <span style="color: #007020; font-weight: bold;">and</span> line[x] <span style="color: #666666;">==</span> <span style="color: #40a070;">0</span> <span style="color: #007020; font-weight: bold;">and</span> line[x<span style="color: #666666;">+</span><span style="color: #40a070;">1</span>]<span style="color: #666666;">!=</span><span style="color: #40a070;">0</span>):
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">True</span>
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">False</span>
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">moveTileNumbers</span>(<span style="color: #007020;">self</span>, tilenumbers, direction):
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">collapseline</span>(line, direction):
<span style="color: #007020; font-weight: bold;">if</span> (direction<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>LEFT <span style="color: #007020; font-weight: bold;">or</span> direction<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>UP):
inc <span style="color: #666666;">=</span> <span style="color: #40a070;">1</span>
rg <span style="color: #666666;">=</span> <span style="color: #007020;">xrange</span>(<span style="color: #40a070;">0</span>, <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span>, inc)
<span style="color: #007020; font-weight: bold;">else</span>:
inc <span style="color: #666666;">=</span> <span style="color: #666666;">-</span><span style="color: #40a070;">1</span>
rg <span style="color: #666666;">=</span> <span style="color: #007020;">xrange</span>(<span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span>, <span style="color: #40a070;">0</span>, inc)
pts <span style="color: #666666;">=</span> <span style="color: #40a070;">0</span>
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> rg:
<span style="color: #007020; font-weight: bold;">if</span> line[i] <span style="color: #666666;">==</span> <span style="color: #40a070;">0</span>:
<span style="color: #007020; font-weight: bold;">continue</span>
<span style="color: #007020; font-weight: bold;">if</span> line[i] <span style="color: #666666;">==</span> line[i<span style="color: #666666;">+</span>inc]:
v <span style="color: #666666;">=</span> line[i]<span style="color: #666666;">*</span><span style="color: #40a070;">2</span>
line[i] <span style="color: #666666;">=</span> v
line[i<span style="color: #666666;">+</span>inc] <span style="color: #666666;">=</span> <span style="color: #40a070;">0</span>
pts <span style="color: #666666;">+=</span> v
<span style="color: #007020; font-weight: bold;">return</span> line, pts
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">moveline</span>(line, directsion):
nl <span style="color: #666666;">=</span> [c <span style="color: #007020; font-weight: bold;">for</span> c <span style="color: #007020; font-weight: bold;">in</span> line <span style="color: #007020; font-weight: bold;">if</span> c <span style="color: #666666;">!=</span> <span style="color: #40a070;">0</span>]
<span style="color: #007020; font-weight: bold;">if</span> directsion<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>UP <span style="color: #007020; font-weight: bold;">or</span> directsion<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>LEFT:
<span style="color: #007020; font-weight: bold;">return</span> nl <span style="color: #666666;">+</span> [<span style="color: #40a070;">0</span>] <span style="color: #666666;">*</span> (<span style="color: #40a070;">4</span> <span style="color: #666666;">-</span> <span style="color: #007020;">len</span>(nl))
<span style="color: #007020; font-weight: bold;">return</span> [<span style="color: #40a070;">0</span>] <span style="color: #666666;">*</span> (<span style="color: #40a070;">4</span> <span style="color: #666666;">-</span> <span style="color: #007020;">len</span>(nl)) <span style="color: #666666;">+</span> nl
score <span style="color: #666666;">=</span> <span style="color: #40a070;">0</span>
<span style="color: #007020; font-weight: bold;">if</span> direction<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>LEFT <span style="color: #007020; font-weight: bold;">or</span> direction<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>RIGHT:
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
origin <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getLine(tilenumbers, i)
line <span style="color: #666666;">=</span> moveline(origin, direction)
collapsed, pts <span style="color: #666666;">=</span> collapseline(line, direction)
new <span style="color: #666666;">=</span> moveline(collapsed, direction)
tilenumbers <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>setLine(tilenumbers, i, new)
score <span style="color: #666666;">+=</span> pts
<span style="color: #007020; font-weight: bold;">elif</span> direction<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>UP <span style="color: #007020; font-weight: bold;">or</span> direction<span style="color: #666666;">==</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>DOWN:
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
origin <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>getCol(tilenumbers, i)
line <span style="color: #666666;">=</span> moveline(origin, direction)
collapsed, pts <span style="color: #666666;">=</span> collapseline(line, direction)
new <span style="color: #666666;">=</span> moveline(collapsed, direction)
tilenumbers <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>setCol(tilenumbers, i, new)
score <span style="color: #666666;">+=</span> pts
<span style="color: #007020; font-weight: bold;">return</span> score, tilenumbers
<span style="color: #60a0b0; font-style: italic;"># AI based on "term2048-AI"</span>
<span style="color: #60a0b0; font-style: italic;"># https://github.com/Nicola17/term2048-AI</span>
<span style="color: #007020; font-weight: bold;">class</span> <span style="color: #0e84b5; font-weight: bold;">AI</span>(<span style="color: #007020;">object</span>):
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">__init__</span>(<span style="color: #007020;">self</span>, board):
<span style="color: #007020;">self</span><span style="color: #666666;">.</span>board <span style="color: #666666;">=</span> board
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">nextMove</span>(<span style="color: #007020;">self</span>):
tilenumbers <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>copyTileNumbers()
m, s <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>nextMoveRecur(tilenumbers[:],<span style="color: #40a070;">3</span>,<span style="color: #40a070;">3</span>)
<span style="color: #007020; font-weight: bold;">return</span> m
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">nextMoveRecur</span>(<span style="color: #007020;">self</span>, tilenumbers, depth, maxDepth, base<span style="color: #666666;">=</span><span style="color: #40a070;">0.9</span>):
bestMove, bestScore <span style="color: #666666;">=</span> <span style="color: #40a070;">0</span>, <span style="color: #666666;">-</span><span style="color: #40a070;">1</span>
<span style="color: #007020; font-weight: bold;">for</span> m <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">1</span>,<span style="color: #40a070;">5</span>):
<span style="color: #007020; font-weight: bold;">if</span>(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>validMove(tilenumbers, m)):
score, newtiles <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>moveTileNumbers(tilenumbers[:], m)
score, critical <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>evaluate(newtiles)
newtiles <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>setCell(newtiles,critical[<span style="color: #40a070;">0</span>],critical[<span style="color: #40a070;">1</span>],<span style="color: #40a070;">2</span>)
<span style="color: #007020; font-weight: bold;">if</span> depth <span style="color: #666666;">!=</span> <span style="color: #40a070;">0</span>:
my_m,my_s <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>nextMoveRecur(newtiles[:],depth<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>,maxDepth)
score <span style="color: #666666;">+=</span> my_s<span style="color: #666666;">*</span><span style="color: #007020;">pow</span>(base,maxDepth<span style="color: #666666;">-</span>depth<span style="color: #666666;">+</span><span style="color: #40a070;">1</span>)
<span style="color: #007020; font-weight: bold;">if</span>(score <span style="color: #666666;">></span> bestScore):
bestMove <span style="color: #666666;">=</span> m
bestScore <span style="color: #666666;">=</span> score
<span style="color: #007020; font-weight: bold;">return</span> bestMove, bestScore
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">evaluate</span>(<span style="color: #007020;">self</span>, tilenumbers, commonRatio<span style="color: #666666;">=</span><span style="color: #40a070;">0.25</span>):
maxVal <span style="color: #666666;">=</span> <span style="color: #40a070;">0.</span>
criticalTile <span style="color: #666666;">=</span> (<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>, <span style="color: #666666;">-</span><span style="color: #40a070;">1</span>)
<span style="color: #007020; font-weight: bold;">for</span> i <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">8</span>):
linearWeightedVal <span style="color: #666666;">=</span> <span style="color: #40a070;">0</span>
invert <span style="color: #666666;">=</span> <span style="color: #007020;">False</span> <span style="color: #007020; font-weight: bold;">if</span> i<span style="color: #666666;"><</span><span style="color: #40a070;">4</span> <span style="color: #007020; font-weight: bold;">else</span> <span style="color: #007020;">True</span>
weight <span style="color: #666666;">=</span> <span style="color: #40a070;">1.</span>
ctile <span style="color: #666666;">=</span> (<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>,<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>)
cond <span style="color: #666666;">=</span> i<span style="color: #666666;">%</span><span style="color: #40a070;">4</span>
<span style="color: #007020; font-weight: bold;">for</span> y <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
<span style="color: #007020; font-weight: bold;">for</span> x <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">4</span>):
<span style="color: #007020; font-weight: bold;">if</span> cond<span style="color: #666666;">==</span><span style="color: #40a070;">0</span>:
b_x <span style="color: #666666;">=</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span><span style="color: #666666;">-</span>x <span style="color: #007020; font-weight: bold;">if</span> invert <span style="color: #007020; font-weight: bold;">else</span> x
b_y <span style="color: #666666;">=</span> y
<span style="color: #007020; font-weight: bold;">elif</span> cond<span style="color: #666666;">==</span><span style="color: #40a070;">1</span>:
b_x <span style="color: #666666;">=</span> x
b_y <span style="color: #666666;">=</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span><span style="color: #666666;">-</span>y <span style="color: #007020; font-weight: bold;">if</span> invert <span style="color: #007020; font-weight: bold;">else</span> y
<span style="color: #007020; font-weight: bold;">elif</span> cond<span style="color: #666666;">==</span><span style="color: #40a070;">2</span>:
b_x <span style="color: #666666;">=</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span><span style="color: #666666;">-</span>x <span style="color: #007020; font-weight: bold;">if</span> invert <span style="color: #007020; font-weight: bold;">else</span> x
b_y <span style="color: #666666;">=</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span><span style="color: #666666;">-</span>y
<span style="color: #007020; font-weight: bold;">elif</span> cond<span style="color: #666666;">==</span><span style="color: #40a070;">3</span>:
b_x <span style="color: #666666;">=</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span><span style="color: #666666;">-</span>x
b_y <span style="color: #666666;">=</span> <span style="color: #40a070;">4</span><span style="color: #666666;">-</span><span style="color: #40a070;">1</span><span style="color: #666666;">-</span>y <span style="color: #007020; font-weight: bold;">if</span> invert <span style="color: #007020; font-weight: bold;">else</span> y
currVal<span style="color: #666666;">=</span><span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>getCell(tilenumbers,b_x,b_y)
<span style="color: #007020; font-weight: bold;">if</span>(currVal <span style="color: #666666;">==</span> <span style="color: #40a070;">0</span> <span style="color: #007020; font-weight: bold;">and</span> ctile <span style="color: #666666;">==</span> (<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>,<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>)):
ctile <span style="color: #666666;">=</span> (b_x,b_y)
linearWeightedVal <span style="color: #666666;">+=</span> currVal<span style="color: #666666;">*</span>weight
weight <span style="color: #666666;">*=</span> commonRatio
invert <span style="color: #666666;">=</span> <span style="color: #007020; font-weight: bold;">not</span> invert
<span style="color: #007020; font-weight: bold;">if</span> linearWeightedVal <span style="color: #666666;">></span> maxVal:
maxVal <span style="color: #666666;">=</span> linearWeightedVal
criticalTile <span style="color: #666666;">=</span> ctile
<span style="color: #007020; font-weight: bold;">return</span> maxVal, criticalTile
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">solveBoard</span>(<span style="color: #007020;">self</span>, moveinterval<span style="color: #666666;">=</span><span style="color: #40a070;">500</span>):
boardHWND <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>getWindowHandle()
<span style="color: #007020; font-weight: bold;">if</span> <span style="color: #007020; font-weight: bold;">not</span> boardHWND:
<span style="color: #007020; font-weight: bold;">return</span> <span style="color: #007020;">False</span>
bx, by, bw, bh <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>boundingRect(<span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>getBoardContour())
x0, x1, y0, y1 <span style="color: #666666;">=</span> bx, bx<span style="color: #666666;">+</span>bw, by, by<span style="color: #666666;">+</span>bh
win32gui<span style="color: #666666;">.</span>SetForegroundWindow(boardHWND)
shell <span style="color: #666666;">=</span> win32com<span style="color: #666666;">.</span>client<span style="color: #666666;">.</span>Dispatch(<span style="color: #4070a0;">'WScript.Shell'</span>)
<span style="color: #007020; font-weight: bold;">print</span> <span style="color: #4070a0;">'Set the focus to the Game Window, and the press this arrow key:'</span>
keymove <span style="color: #666666;">=</span> [<span style="color: #4070a0;">'UP'</span>, <span style="color: #4070a0;">'DOWN'</span>, <span style="color: #4070a0;">'LEFT'</span>, <span style="color: #4070a0;">'RIGHT'</span>]
delay <span style="color: #666666;">=</span> moveinterval <span style="color: #666666;">/</span> <span style="color: #40a070;">3</span> <span style="color: #60a0b0; font-style: italic;"># milliseconds delay to cancel board animation effect</span>
prev_numbers <span style="color: #666666;">=</span> []
<span style="color: #007020; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
numbers, inframe, outframe <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>update()
<span style="color: #007020; font-weight: bold;">if</span> numbers <span style="color: #666666;">!=</span> prev_numbers:
cv2<span style="color: #666666;">.</span>waitKey(delay)
numbers, inframe, outframe <span style="color: #666666;">=</span> <span style="color: #007020;">self</span><span style="color: #666666;">.</span>board<span style="color: #666666;">.</span>update()
<span style="color: #007020; font-weight: bold;">if</span> numbers <span style="color: #666666;">==</span> prev_numbers: <span style="color: #60a0b0; font-style: italic;"># recheck if has changed</span>
<span style="color: #007020; font-weight: bold;">continue</span>
prev_numbers <span style="color: #666666;">=</span> numbers
move <span style="color: #666666;">=</span> ai<span style="color: #666666;">.</span>nextMove()
<span style="color: #007020; font-weight: bold;">if</span> move:
key <span style="color: #666666;">=</span> keymove[move<span style="color: #666666;">-</span><span style="color: #40a070;">1</span>]
shell<span style="color: #666666;">.</span>SendKeys(<span style="color: #4070a0;">'{</span><span style="color: #70a0d0; font-style: italic;">%s</span><span style="color: #4070a0;">}'</span><span style="color: #666666;">%</span>key)
<span style="color: #007020; font-weight: bold;">print</span> key
cv2<span style="color: #666666;">.</span>waitKey(delay)
cv2<span style="color: #666666;">.</span>imshow(<span style="color: #4070a0;">'CV copy'</span>,inframe[y0:y1,x0:x1])
cv2<span style="color: #666666;">.</span>imshow(<span style="color: #4070a0;">'CV out'</span>, outframe[y0:y1,x0:x1])
cv2<span style="color: #666666;">.</span>waitKey(delay)
cv2<span style="color: #666666;">.</span>destroyWindow( <span style="color: #4070a0;">'CV copy'</span> )
cv2<span style="color: #666666;">.</span>destroyWindow( <span style="color: #4070a0;">'CV out'</span> )
<span style="color: #60a0b0; font-style: italic;"># http://gabrielecirulli.github.io/2048/</span>
<span style="color: #60a0b0; font-style: italic;"># http://ov3y.github.io/2048-AI/</span>
board <span style="color: #666666;">=</span> Board(<span style="color: #4070a0;">"2048 - Google Chrome"</span>)
<span style="color: #60a0b0; font-style: italic;">#board = Board("2048 - Mozilla Firefox")</span>
ai <span style="color: #666666;">=</span> AI(board)
ai<span style="color: #666666;">.</span>solveBoard(<span style="color: #40a070;">360</span>)
<span style="color: #007020; font-weight: bold;">print</span> <span style="color: #4070a0;">'stopped.'</span>
</pre></div>download: <a href="https://code.google.com/p/yus-repo/source/browse/trunk/OpenCV/2048gamesolver/2048opencv.py">2048opencv.py</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzRPhyphenhyphenjNNoFyp1ni0dHJyljvTUYDVFaD09iMo_-OkRWHsYi0HKqzCBfwNINWlDG4F_omGGGKfMMkHrfXtV_wOn8dlZeakrPjitjI66mpcVZfb7j56lAN887PTsH256sxOtBi9CDClK3D0r/s1600/orig.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzRPhyphenhyphenjNNoFyp1ni0dHJyljvTUYDVFaD09iMo_-OkRWHsYi0HKqzCBfwNINWlDG4F_omGGGKfMMkHrfXtV_wOn8dlZeakrPjitjI66mpcVZfb7j56lAN887PTsH256sxOtBi9CDClK3D0r/s1600/orig.png" height="400" width="276" /></a></div><div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;"><pre style="line-height: 125%; margin: 0;"><span style="color: #60a0b0; font-style: italic;"># open this site with Chrome: http://gabrielecirulli.github.io/2048/</span>
board <span style="color: #666666;">=</span> Board(<span style="color: #4070a0;">"2048 - Google Chrome"</span>)
ai <span style="color: #666666;">=</span> AI(board)
ai<span style="color: #666666;">.</span>solveBoard()
</pre></div><table><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbxStkSWnT2k9eO743mDeSWyILGWpN_PcMy1Gt6rzO-yDqoLRyuYhTDf-5lH39D88rDomuCsgrc982jTlioXdBRLXtroVdhr4afrYGxRIDdbynR7OAjAJUniv-8JSaJ-j_WMC7zHAZ1phe/s1600/copy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbxStkSWnT2k9eO743mDeSWyILGWpN_PcMy1Gt6rzO-yDqoLRyuYhTDf-5lH39D88rDomuCsgrc982jTlioXdBRLXtroVdhr4afrYGxRIDdbynR7OAjAJUniv-8JSaJ-j_WMC7zHAZ1phe/s1600/copy.png" height="200" width="184" /></a></td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjww8l_8cx7D-gu0l1w2g_vTb4xXm-o4Zlms2Bx_31S087wNjECK884hGlhAlUCnCBJj9jsVWi1b7CQneTtVEJmJ96vKWTqXuG-jIBmnguFmh2i2Ji-rcxc73v4HaLsJ3jRCPb9qBnF5Whx/s1600/output.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjww8l_8cx7D-gu0l1w2g_vTb4xXm-o4Zlms2Bx_31S087wNjECK884hGlhAlUCnCBJj9jsVWi1b7CQneTtVEJmJ96vKWTqXuG-jIBmnguFmh2i2Ji-rcxc73v4HaLsJ3jRCPb9qBnF5Whx/s1600/output.png" height="200" width="184" /></a></td></tr>
</tbody></table><br />
demo video:<br />
<iframe width="420" height="315" src="//www.youtube.com/embed/8oYV1cbJIb0" frameborder="0" allowfullscreen></iframe><br />
<br />
==================================<br />
update:<br />
Solving the Android version of 2048..<br />
<i>Android phone is running a VNC server (vnc server & viewer are both slow!).</i><br />
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/mfp9u0FT054" width="420"></iframe><br />
python script: <a href="https://code.google.com/p/yus-repo/source/browse/trunk/OpenCV/2048gamesolver/2048opencv_adb.py" target="_blank">2048opencv_adb.py</a><br />
<br />
<i>tip:</i> send [touchscreen]swipe event through adb:<br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;"><pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">adb shell input swipe x1 y1 x2 y2</span>
</pre></div><br />
<br />
sources:<br />
<a href="http://gabrielecirulli.github.io/2048/">gabrielecirulli.github</a><br />
<a href="http://diaryofatinker.blogspot.com/2014/03/an-artificial-intelligence-for-2048-game.html" target="_blank">diaryofatinker.blogspot</a><br />
<a href="http://stackoverflow.com/questions/22342854/what-is-the-optimal-algorithm-for-the-game-2048">stackoverflow.com</a><br />
<br />
<div id="fb-root"></div><script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script><br />
<div class="fb-share-button" data-type="button_count" style="margin-bottom: 20px;"></div>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com9tag:blogger.com,1999:blog-3967613250975275925.post-67706266183739146722014-07-21T12:16:00.001+08:002014-07-21T14:59:02.911+08:00OpenCV Python: Digit RecognitionHere's an example of OpenCV digit recognition with a given <b>TrueType</b> font (*.ttf) and digit height. It uses python <a href="https://pypi.python.org/pypi/Pillow" target="_blank">PIL module</a> to load digit glyphs. These glyphs (converted to CV images) are then used to train a <a href="http://docs.opencv.org/modules/ml/doc/k_nearest_neighbors.html" target="_blank">K-Nearest</a> model.<br />
<br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; height: 480px; overflow: auto; padding: .2em .6em; width: auto;"><pre style="line-height: 125%; margin: 0;"><span style="color: #007020; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">cv2</span>
<span style="color: #007020; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">numpy</span> <span style="color: #007020; font-weight: bold;">as</span> <span style="color: #0e84b5; font-weight: bold;">np</span>
<span style="color: #007020; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">PIL</span> <span style="color: #007020; font-weight: bold;">import</span> Image, ImageFont, ImageDraw, ImageOps
<span style="color: #60a0b0; font-style: italic;"># create training model based on the given TTF font file</span>
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">createDigitsModel</span>(fontfile, digitheight):
ttfont <span style="color: #666666;">=</span> ImageFont<span style="color: #666666;">.</span>truetype(fontfile, digitheight)
samples <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>empty((<span style="color: #40a070;">0</span>,digitheight<span style="color: #666666;">*</span>(digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>)))
responses <span style="color: #666666;">=</span> []
<span style="color: #007020; font-weight: bold;">for</span> n <span style="color: #007020; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #40a070;">10</span>):
pil_im <span style="color: #666666;">=</span> Image<span style="color: #666666;">.</span>new(<span style="color: #4070a0;">"RGB"</span>, (digitheight, digitheight<span style="color: #666666;">*</span><span style="color: #40a070;">2</span>))
ImageDraw<span style="color: #666666;">.</span>Draw(pil_im)<span style="color: #666666;">.</span>text((<span style="color: #40a070;">0</span>, <span style="color: #40a070;">0</span>), <span style="color: #007020;">str</span>(n), font<span style="color: #666666;">=</span>ttfont)
pil_im <span style="color: #666666;">=</span> pil_im<span style="color: #666666;">.</span>crop(pil_im<span style="color: #666666;">.</span>getbbox())
pil_im <span style="color: #666666;">=</span> ImageOps<span style="color: #666666;">.</span>invert(pil_im)
<span style="color: #60a0b0; font-style: italic;">#pil_im.save(str(n) + ".png")</span>
<span style="color: #60a0b0; font-style: italic;"># convert to cv image</span>
cv_image <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(np<span style="color: #666666;">.</span>array( pil_im ), cv2<span style="color: #666666;">.</span>COLOR_RGBA2BGRA)
gray <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(cv_image, cv2<span style="color: #666666;">.</span>COLOR_BGR2GRAY)
blur <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>GaussianBlur(gray,(<span style="color: #40a070;">5</span>,<span style="color: #40a070;">5</span>),<span style="color: #40a070;">0</span>)
thresh <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>adaptiveThreshold(blur,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">11</span>,<span style="color: #40a070;">2</span>)
roi <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>resize(thresh,(digitheight,digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>))
responses<span style="color: #666666;">.</span>append( n )
sample <span style="color: #666666;">=</span> roi<span style="color: #666666;">.</span>reshape((<span style="color: #40a070;">1</span>,digitheight<span style="color: #666666;">*</span>(digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>)))
samples <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>append(samples,sample,<span style="color: #40a070;">0</span>)
samples <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>array(samples,np<span style="color: #666666;">.</span>float32)
responses <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>array(responses,np<span style="color: #666666;">.</span>float32)
model <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>KNearest()
model<span style="color: #666666;">.</span>train(samples,responses)
<span style="color: #007020; font-weight: bold;">return</span> model
<span style="color: #60a0b0; font-style: italic;"># digit recognition part</span>
<span style="color: #007020; font-weight: bold;">def</span> <span style="color: #06287e;">findDigits</span>(imagefile, digitheight, fontfile<span style="color: #666666;">=</span><span style="color: #4070a0;">"C:</span><span style="color: #4070a0; font-weight: bold;">\\</span><span style="color: #4070a0;">Windows</span><span style="color: #4070a0; font-weight: bold;">\\</span><span style="color: #4070a0;">Fonts</span><span style="color: #4070a0; font-weight: bold;">\\</span><span style="color: #4070a0;">Arial.ttf"</span>):
im <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>imread(imagefile)
out <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>zeros(im<span style="color: #666666;">.</span>shape,np<span style="color: #666666;">.</span>uint8)
gray <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>cvtColor(im,cv2<span style="color: #666666;">.</span>COLOR_BGR2GRAY)
thresh <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>adaptiveThreshold(gray,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">1</span>,<span style="color: #40a070;">11</span>,<span style="color: #40a070;">2</span>)
contours,hierarchy <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>findContours(thresh<span style="color: #666666;">.</span>copy(),cv2<span style="color: #666666;">.</span>RETR_EXTERNAL ,cv2<span style="color: #666666;">.</span>CHAIN_APPROX_SIMPLE)
model <span style="color: #666666;">=</span> createDigitsModel(fontfile, digitheight)
<span style="color: #007020; font-weight: bold;">for</span> cnt <span style="color: #007020; font-weight: bold;">in</span> contours:
x,y,w,h <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>boundingRect(cnt)
<span style="color: #007020; font-weight: bold;">if</span> h<span style="color: #666666;">></span>w <span style="color: #007020; font-weight: bold;">and</span> h<span style="color: #666666;">></span>(digitheight<span style="color: #666666;">*</span><span style="color: #40a070;">4</span>)<span style="color: #666666;">/</span><span style="color: #40a070;">5</span> <span style="color: #007020; font-weight: bold;">and</span> h<span style="color: #666666;"><</span>(digitheight<span style="color: #666666;">*</span><span style="color: #40a070;">6</span>)<span style="color: #666666;">/</span><span style="color: #40a070;">5</span>: <span style="color: #60a0b0; font-style: italic;">#+/-20%</span>
cv2<span style="color: #666666;">.</span>rectangle(im,(x,y),(x<span style="color: #666666;">+</span>w,y<span style="color: #666666;">+</span>h),(<span style="color: #40a070;">0</span>,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">0</span>),<span style="color: #40a070;">1</span>)
roi <span style="color: #666666;">=</span> thresh[y:y<span style="color: #666666;">+</span>h,x:x<span style="color: #666666;">+</span>w] <span style="color: #60a0b0; font-style: italic;"># crop</span>
roi <span style="color: #666666;">=</span> cv2<span style="color: #666666;">.</span>resize(roi,(digitheight,digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>))
roi <span style="color: #666666;">=</span> roi<span style="color: #666666;">.</span>reshape((<span style="color: #40a070;">1</span>,digitheight<span style="color: #666666;">*</span>(digitheight<span style="color: #666666;">/</span><span style="color: #40a070;">2</span>)))
roi <span style="color: #666666;">=</span> np<span style="color: #666666;">.</span>float32(roi)
retval, results, neigh_resp, dists <span style="color: #666666;">=</span> model<span style="color: #666666;">.</span>find_nearest(roi, k<span style="color: #666666;">=</span><span style="color: #40a070;">1</span>)
string <span style="color: #666666;">=</span> <span style="color: #007020;">str</span>(<span style="color: #007020;">int</span>((results[<span style="color: #40a070;">0</span>][<span style="color: #40a070;">0</span>])))
<span style="color: #60a0b0; font-style: italic;">#cv2.drawContours(out,[cnt],-1,(0,255,255),1)</span>
cv2<span style="color: #666666;">.</span>putText(out,string,(x,y<span style="color: #666666;">+</span>h),<span style="color: #40a070;">0</span>,<span style="color: #40a070;">1</span>,(<span style="color: #40a070;">0</span>,<span style="color: #40a070;">255</span>,<span style="color: #40a070;">0</span>))
cv2<span style="color: #666666;">.</span>imshow(<span style="color: #4070a0;">'in'</span>,im)
cv2<span style="color: #666666;">.</span>imshow(<span style="color: #4070a0;">'out'</span>,out)
cv2<span style="color: #666666;">.</span>waitKey(<span style="color: #40a070;">0</span>)
cv2<span style="color: #666666;">.</span>destroyWindow( <span style="color: #4070a0;">'in'</span> )
cv2<span style="color: #666666;">.</span>destroyWindow( <span style="color: #4070a0;">'out'</span> )
findDigits(<span style="color: #4070a0;">'pi.png'</span>, <span style="color: #40a070;">32</span>)
<span style="color: #007020; font-weight: bold;">print</span> <span style="color: #4070a0;">'done.'</span>
</pre></div>download: <a href="http://code.google.com/p/yus-repo/source/browse/trunk/OpenCV/digitrecognition/digitrecognition.py" target="_blank">digitrecognition.py</a><br />
<br />
sources:<br />
<a href="http://opencvpython.blogspot.com/2012/04/simple-digit-recognition-ocr-in-opencv.html" rel="" target="_blank">opencvpython.blogspot.com</a><br />
<a href="http://stackoverflow.com/questions/9413216/simple-digit-recognition-ocr-in-opencv-python" target="_blank">stackoverflow.com</a><br />
<br />
<div id="fb-root"></div><script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script><br />
<div class="fb-share-button" data-type="button_count" style="margin-bottom: 20px;"></div>'yushttp://www.blogger.com/profile/09469609276942488473noreply@blogger.com0