{"id":964,"date":"2020-08-15T00:03:17","date_gmt":"2020-08-15T04:03:17","guid":{"rendered":"https:\/\/www.andersknelson.com\/blog\/?p=964"},"modified":"2025-05-12T18:09:24","modified_gmt":"2025-05-12T22:09:24","slug":"asian-flexible-led-matrix","status":"publish","type":"post","link":"https:\/\/www.andersknelson.com\/blog\/?p=964","title":{"rendered":"Asian Flexible LED matrix"},"content":{"rendered":"\n<p>While looking at some LED facemask projects online, I came across a neat new flexible RGB LED matrix with BLE connectivity. It has 32&#215;16 RGB pixels but the mobile app it uses will only send full-on primary color combinations, i.e. it&#8217;s not full color. Cost is ~$40.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Components<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Markings: [HC89F0541 | 2011 | A7616511]. Qty: 1. Holychip 8051 MCU, <a href=\"https:\/\/lcsc.com\/product-detail\/Other-Processors-and-Microcontrollers-MCUs_Shanghai-Holychip-Elec-HC89F0541-LQFP32-Y-M_C710314.html\">Link<\/a>.<\/li>\n\n\n\n<li>Markings: [SM16206S | BZBCNNAC17]. Qty: 6. Sunmoon 16 channel constant-current LED sink driver, <a href=\"https:\/\/lcsc.com\/product-detail\/LED-Drivers_Shenzhen-Sunmoon-Micro-SM16106SC_C121618.html\">Link<\/a>.<\/li>\n\n\n\n<li>Markings: [D7258 | 2009CF]. Qty: 2. Double Microelectronics 8 channel LED source driver, <a href=\"https:\/\/lcsc.com\/product-detail\/LED-Drivers_DBIC-Double-Microelectronics-D7258_C97365.html\">Link<\/a>.<\/li>\n\n\n\n<li>2mm x 2mm RGB LED. Qty: 512.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Analysis<\/h2>\n\n\n\n<p>4 wires go from the BLE\/battery pack labeled VCC, TXD1, RXD1 and GND. I used my Saleae Logic16 to see what the TXD\/RXD waveforms looked like, focusing on length of data bit periods. You can view the below logic traces in <a href=\"https:\/\/ideas.saleae.com\/f\/changelog\/\">Logic2<\/a>:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/off_to_on-1.sal_.zip\">off_to_on-1.sal<\/a><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/off_to_on-1.sal_.zip\" class=\"wp-block-file__button wp-element-button\" download>Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_pattern-1.sal_.zip\">on_to_pattern-1.sal<\/a><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_pattern-1.sal_.zip\" class=\"wp-block-file__button wp-element-button\" download>Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_graffiti-1.sal_.zip\">on_to_static_graffiti-1.sal<\/a><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_graffiti-1.sal_.zip\" class=\"wp-block-file__button wp-element-button\" download>Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_text-1.sal_.zip\">on_to_static_text-1.sal<\/a><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_text-1.sal_.zip\" class=\"wp-block-file__button wp-element-button\" download>Download<\/a><\/div>\n\n\n\n<p>To save time I used a <a href=\"https:\/\/www.unitjuggler.com\/convert-frequency-from-%C2%B5s(p)-to-Hz.html?val=101\">web calculator<\/a> to convert from period to frequency. Seeing a falling edge before every packet and bit periods of 28\u00b5s -&gt; 35714Hz I figured we had a UART at ~38400 baud. Setting an Async serial analyzer in Logic2 showed what looks to be meaningful data. I exported the incoming data (in hex):<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_pattern-1.csv\">on_to_pattern-1<\/a><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_pattern-1.csv\" class=\"wp-block-file__button wp-element-button\" download>Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_graffiti-1.csv\">on_to_static_graffiti-1<\/a><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_graffiti-1.csv\" class=\"wp-block-file__button wp-element-button\" download>Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_text-1.csv\">on_to_static_text-1<\/a><a href=\"https:\/\/www.andersknelson.com\/blog\/wp-content\/uploads\/2020\/08\/on_to_static_text-1.csv\" class=\"wp-block-file__button wp-element-button\" download>Download<\/a><\/div>\n\n\n\n<p>RXD, however, is another story. The shortest bit period on RXD is 101\u00b5s, with others being 202\u00b5s and packetized with a ~5ms preamble of zeroes. Assigning an Async analyzer at 101\u00b5s -&gt; 9900Hz -&gt; ~9600 baud yielded garbage (framing errors everywhere). 10K baud also yielded nothing. Given this is a product in the LED space, I assigned a WS2812B analyzer in Logic2 but that also produced nothing useful. Weird, I&#8217;ll have to look closer.<\/p>\n\n\n\n<p>There are (32 x 16 x 3) = 1536 LED die on the display. Since this display only drives each die fully ON or OFF, we should be able to represent each die with a single bit. I expect the display data for a single frame will then be (1536\/8) = 192 bytes.<\/p>\n\n\n\n<p>I entered enough text to cover 3 full frames, so I expect to see (192*3) = 576 bytes go by, ignoring protocol overhead.<\/p>\n\n\n\n<p>TO BE CONTINUED&#8230; Feel free to drop any insight into the comments!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Gallery<\/h2>\n\n\n\n<p><a href=\"https:\/\/photos.app.goo.gl\/jSVbuV63Ces4N1gi7\">https:\/\/photos.app.goo.gl\/jSVbuV63Ces4N1gi7<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>While looking at some LED facemask projects online, I came [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":978,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,37],"tags":[],"class_list":["post-964","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-projects","category-unfinished"],"_links":{"self":[{"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/964","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=964"}],"version-history":[{"count":13,"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/964\/revisions"}],"predecessor-version":[{"id":1279,"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/964\/revisions\/1279"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=\/wp\/v2\/media\/978"}],"wp:attachment":[{"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.andersknelson.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}