{"id":1282,"date":"2017-01-10T17:01:42","date_gmt":"2017-01-10T15:01:42","guid":{"rendered":"https:\/\/www.kurokesu.com\/main\/?p=1282"},"modified":"2017-01-10T19:32:18","modified_gmt":"2017-01-10T17:32:18","slug":"it-takes-two-raspberries-to-run-a-clock","status":"publish","type":"post","link":"https:\/\/www.kurokesu.com\/main\/2017\/01\/10\/it-takes-two-raspberries-to-run-a-clock\/","title":{"rendered":"It takes two Raspberries to run a clock"},"content":{"rendered":"<p>Despite lousy title, I will tell my success story how to add visual output to well known IoT tool called Node-RED. One Raspberry Pi, let&#8217;s call it <strong>RPI-RED<\/strong>, will be running <a href=\"http:\/\/nodered.org\/\">Node-RED<\/a> another one <strong>RPI-LED<\/strong> will be dedicated to server LED panel.<\/p>\n<p>First you should should install Node-RED to <strong>RPI-RED.<\/strong> Installation is <a href=\"https:\/\/www.kurokesu.com\/main\/2017\/01\/09\/node-red-for-rapid-hardware-wiring\/\">well described<\/a> in previous post.<\/p>\n<p>Also diagram below illustrates all necessary parts for system to be running. This topology can be scaled up by adding more LED panels and used for example to manage queues, display traffic signs, show discounts in larger shopping center, etc.<\/p>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1309\" src=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/Untitled3_.png\" width=\"500\" height=\"327\" srcset=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/Untitled3_.png 1500w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/Untitled3_-300x196.png 300w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/Untitled3_-768x503.png 768w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/Untitled3_-1024x670.png 1024w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/>\n<p>Component list:<\/p>\n<ul>\n<li>Raspberry Pi\u00a0 x2<\/li>\n<li><a href=\"http:\/\/www.kurokesu.com\/shop\/led_panels\/LEDPAN1_064032\">LED panel<\/a><\/li>\n<li><a href=\"http:\/\/www.kurokesu.com\/shop\/led_panels\/RPI-HUB75-P-3\">HUB-75 adapter<\/a><\/li>\n<li>5V power supply for LED panel not less than 18W<\/li>\n<li>5V supply for Raspberry Pi x2<\/li>\n<\/ul>\n<h2>Install LED control software to RPI-LED<\/h2>\n<p>As usual, install jessie lite, setup headless mode by enabling ssh server and install <strong>rpi-rgb-led-matrix<\/strong> from <a href=\"https:\/\/github.com\/hzeller\/rpi-rgb-led-matrix\">hzeller github repository<\/a>. His repository is primary information source how to work with these panels, and if you fall into any issues, please read it first as I will be covering it very briefly. More panels can be connected to single Raspberry remember <a href=\"https:\/\/www.kurokesu.com\/main\/2016\/07\/06\/more-pixels\/\">9*9 arrangement<\/a> playing video?<\/p>\n<pre>sudo apt-get install -y git\r\ncd ~\r\ngit clone https:\/\/github.com\/hzeller\/rpi-rgb-led-matrix.git\r\ncd rpi-rgb-led-matrix\r\nmake -C examples-api-use\r\n<\/pre>\n<p>That&#8217;s it. Now let&#8217;s test if we have working hardware.<\/p>\n<h2>Test if LED panel works<\/h2>\n<ul>\n<li>Unplug USB power from <strong>RPI-LED<\/strong><\/li>\n<li>Connect HUB-75 adapter<\/li>\n<li>Connect LED panel<\/li>\n<li>Connect 5V power to panel<\/li>\n<\/ul>\n<p>It should look like this<\/p>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1298\" src=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8708_r.jpg\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8708_r.jpg 1500w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8708_r-300x200.jpg 300w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8708_r-768x512.jpg 768w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8708_r-1024x683.jpg 1024w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/>\n<p>Run included demo:<\/p>\n<pre>cd ~\/rpi-rgb-led-matrix\r\nsudo examples-api-use\/demo -c2 -D0<\/pre>\n<p>You should see nice demo, which will indicate you done well and all major parts are working.<\/p>\n<h2>Run Python sample project<\/h2>\n<p>It is time to step one more level up &#8211; control LED panel from Python script. Install Python and some libraries.<\/p>\n<pre>cd ~\/rpi-rgb-led-matrix\/python\r\nsudo apt-get install -y python\r\nsudo apt-get install -y python-imaging\r\nsudo python setup.py install\r\n<\/pre>\n<p>Now check if python samples work:<\/p>\n<pre>cd ~\/rpi-rgb-led-matrix\/python\/samples\r\nsudo python image-scroller.py<\/pre>\n<p>You should see LED panel working again. Good, we are close to our goal.<\/p>\n<h2>Interface to Node-RED over MQTT<\/h2>\n<p>MQTT is de-facto standard for many Internet connected devices and is basically used for packet communication in a publish\/subscription manner. There are tons of information about it, and if necessary feel free to start from <a href=\"http:\/\/mqtt.org\/\">mqtt.org<\/a>. Install python bindings for MQTT called paho.<\/p>\n<pre>sudo pip install paho-mqtt\r\n<\/pre>\n<p>That&#8217;s it. Now when we have ability to speak to Node-RED, let&#8217;s connect all parts together.<\/p>\n<h2>Connect all strings together<\/h2>\n<p>If you completed all steps correctly, this setup will allow you to:<\/p>\n<ul>\n<li>Insert visual blocks into Node-RED editor<\/li>\n<li>Assign various tasks and functions<\/li>\n<li>Communicate with world using various protocols like TCP, UDP, WebSockets, MQTT and some more protocols<\/li>\n<li>Control GPIO pins<\/li>\n<li>Create simple User Interface directly from Nore-RED<\/li>\n<li>Receive and aggregate sensor data<\/li>\n<li>Insert data into database and run queries<\/li>\n<li>And much more<\/li>\n<\/ul>\n<p>After completing my tutorial you should see result like in picture below. I tried to keep demonstration as simple as possible. Ideas for future can cover graphing historical temperature data, adding weather forecasts with icons, displaying notifications from google calendar, adjusting brightness according to date time or actual sensor data&#8230; I could go on for a long time naming possible usage scenarios.<\/p>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1299\" src=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8724_r.jpg\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8724_r.jpg 1500w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8724_r-300x200.jpg 300w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8724_r-768x512.jpg 768w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8724_r-1024x683.jpg 1024w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/>\n<h2>Node-RED flow<\/h2>\n<p>This flow aggregates timestamp and temperature sensor from MQTT. Adds text parameters like position, color, font to message and emits it to MQTT server at topic <strong>\/ledpanel\/1<\/strong>.<\/p>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1302\" src=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/12.png\" width=\"600\" height=\"283\" srcset=\"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/12.png 879w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/12-300x141.png 300w, https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/12-768x362.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/>\n<p>Below is a json line to import directly into Node-RED. Adjust MQTT credentials as needed.<\/p>\n<pre>[{\"id\":\"1fa87483.b31adb\",\"type\":\"mqtt out\",\"z\":\"48807c1d.6db04c\",\"name\":\"\",\"topic\":\"ledpanel\/1\",\"qos\":\"\",\"retain\":\"\",\"broker\":\"5252913.f77dff\",\"x\":1004.88330078125,\"y\":180.88333129882812,\"wires\":[]},{\"id\":\"6cbafc93.dc906c\",\"type\":\"inject\",\"z\":\"48807c1d.6db04c\",\"name\":\"\",\"topic\":\"text\",\"payload\":\"--:--\",\"payloadType\":\"str\",\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"x\":564.88330078125,\"y\":237.88333129882812,\"wires\":[[\"b5190bb3.c7181\"]]},{\"id\":\"b5190bb3.c7181\",\"type\":\"function\",\"z\":\"48807c1d.6db04c\",\"name\":\"CLOCK\",\"func\":\"var ret = {};\\n\\nret[\\\"text\\\"] = msg.payload;\\n\\nret[\\\"x\\\"] = 5;\\nret[\\\"y\\\"] = 1;\\n\\nret[\\\"red\\\"] = 100;\\nret[\\\"green\\\"] = 100;\\nret[\\\"blue\\\"] = 100;\\n\\nret[\\\"font\\\"] = 19;\\n\\nret[\\\"function\\\"] = \\\"set_text\\\";\\n\\nmsg.payload = ret;\\n\/\/msg.topic = \\\"set_text\\\";\\n\\n\\nreturn msg;\\n\",\"outputs\":1,\"noerr\":0,\"x\":793.88330078125,\"y\":238.88333129882812,\"wires\":[[\"1fa87483.b31adb\"]]},{\"id\":\"33e7699a.52912e\",\"type\":\"inject\",\"z\":\"48807c1d.6db04c\",\"name\":\"CLEAR\",\"topic\":\"\",\"payload\":\"TEST123 \",\"payloadType\":\"str\",\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"x\":639.88330078125,\"y\":106.88333129882812,\"wires\":[[\"abd7dc51.9b6068\"]]},{\"id\":\"abd7dc51.9b6068\",\"type\":\"function\",\"z\":\"48807c1d.6db04c\",\"name\":\"CLEAR\",\"func\":\"var ret = {};\\n\\nret[\\\"red\\\"] = 0;\\nret[\\\"green\\\"] = 0;\\nret[\\\"blue\\\"] = 0;\\n\\nret[\\\"function\\\"] = \\\"clear\\\";\\n\\nmsg.payload = ret;\\n\\nreturn msg;\\n\",\"outputs\":1,\"noerr\":0,\"x\":789.88330078125,\"y\":111.88333129882812,\"wires\":[[\"1fa87483.b31adb\"]]},{\"id\":\"de7eba35.0d97c\",\"type\":\"function\",\"z\":\"48807c1d.6db04c\",\"name\":\"TEMPER\",\"func\":\"var ret = {};\\n\\nret[\\\"text\\\"] = msg.payload+\\\"\u00a0 \\\";\\n\\nret[\\\"x\\\"] = 1;\\nret[\\\"y\\\"] = 24;\\n\\nret[\\\"red\\\"] = 30;\\nret[\\\"green\\\"] = 30;\\nret[\\\"blue\\\"] = 30;\\n\\nret[\\\"font\\\"] = 13;\\n\\nret[\\\"function\\\"] = \\\"set_text\\\";\\n\\nmsg.payload = ret;\\n\/\/msg.topic = \\\"set_text\\\";\\n\\n\\nreturn msg;\\n\",\"outputs\":1,\"noerr\":0,\"x\":742.88330078125,\"y\":398.8833312988281,\"wires\":[[\"1fa87483.b31adb\"]]},{\"id\":\"c074145a.2b11e8\",\"type\":\"function\",\"z\":\"48807c1d.6db04c\",\"name\":\"Timestamp to HH:MM\",\"func\":\"\/\/msg.timestamp= new Date().toISOString()\\n\\nvar now\u00a0\u00a0\u00a0\u00a0 = new Date(); \\nvar year\u00a0\u00a0\u00a0 = now.getFullYear();\\nvar month\u00a0\u00a0 = now.getMonth()+1; \\nvar day\u00a0\u00a0\u00a0\u00a0 = now.getDate();\\nvar hour\u00a0\u00a0\u00a0 = now.getHours();\\nvar minute\u00a0 = now.getMinutes();\\nvar second\u00a0 = now.getSeconds(); \\n\\nif(month.toString().length == 1) {\\n\u00a0\u00a0\u00a0 var month = '0'+month;\\n}\\n\\nif(day.toString().length == 1) {\\n\u00a0\u00a0\u00a0 var day = '0'+day;\\n}\u00a0\u00a0 \\n\\nif(hour.toString().length == 1) {\\n\u00a0\u00a0\u00a0 var hour = '0'+hour;\\n}\\n\\nif(minute.toString().length == 1) {\\n\u00a0\u00a0\u00a0 var minute = '0'+minute;\\n}\\n\\nif(second.toString().length == 1) {\\n\u00a0\u00a0\u00a0 var second = '0'+second;\\n}\u00a0\u00a0 \\n\\n\/\/msg.timestamp = year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second;\\nmsg.payload = hour+':'+minute;\\n\\n\\nreturn msg;\",\"outputs\":1,\"noerr\":0,\"x\":575.8833312988281,\"y\":179.88333129882812,\"wires\":[[\"b5190bb3.c7181\"]]},{\"id\":\"4cb27606.e94b2\",\"type\":\"inject\",\"z\":\"48807c1d.6db04c\",\"name\":\"Time\",\"topic\":\"text\",\"payload\":\"\",\"payloadType\":\"str\",\"repeat\":\"1\",\"crontab\":\"\",\"once\":false,\"x\":388.7666320800781,\"y\":179.01666259765625,\"wires\":[[\"c074145a.2b11e8\"]]},{\"id\":\"6064ceae.493248\",\"type\":\"mqtt in\",\"z\":\"48807c1d.6db04c\",\"name\":\"TE923 \/ TC\",\"topic\":\"sensors\/namai\/te923\/TC\",\"qos\":\"2\",\"broker\":\"5252913.f77dff\",\"x\":533.9999389648438,\"y\":345.1832580566406,\"wires\":[[\"de7eba35.0d97c\"]]},{\"id\":\"4247a366.78dbb4\",\"type\":\"inject\",\"z\":\"48807c1d.6db04c\",\"name\":\"\",\"topic\":\"text\",\"payload\":\"--.-\",\"payloadType\":\"str\",\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"x\":511.8833312988281,\"y\":402.8833312988281,\"wires\":[[\"de7eba35.0d97c\"]]},{\"id\":\"5252913.f77dff\",\"type\":\"mqtt-broker\",\"z\":\"\",\"broker\":\"127.0.0.1\",\"port\":\"1883\",\"clientid\":\"\",\"usetls\":false,\"compatmode\":true,\"keepalive\":\"60\",\"cleansession\":true,\"willTopic\":\"\",\"willQos\":\"0\",\"willPayload\":\"\",\"birthTopic\":\"\",\"birthQos\":\"0\",\"birthPayload\":\"\"}]<\/pre>\n<p>After deployment it should start emitting time every second and temperature as soon as it receives message from external temperature sensor. Temperature values comes from <a href=\"http:\/\/lukse.lt\/uzrasai\/2014-08-jutikliu-duomenu-surinkimas-ir-atvaizdavimas\/\">TE923 weather station<\/a> which I hacked 2 years ago.<\/p>\n<h3>LED control Python code<\/h3>\n<p>This is minimalistic\u00a0 code to illustrate design flow. It implements two functions: <strong>set text<\/strong> and <strong>clean display<\/strong>, which is enough to demonstrate basic functionality. Feel free to use and abuse it.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/Lukse\/ff4297ee1d7ac4c531e089c37c205462.js\"><\/script><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Despite lousy title, I will tell my success story how to add visual output to well known IoT tool called Node-RED. One Raspberry Pi, let&#8217;s call it RPI-RED, will be running Node-RED another one RPI-LED will be dedicated to server LED panel. First you should should install Node-RED to RPI-RED. Installation is well described in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1298,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[153],"tags":[232,231,34,36,210,207,49,33],"class_list":["post-1282","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-projects","tag-hub-75","tag-hzeller","tag-led","tag-led-panel","tag-mqtt","tag-node-red","tag-python","tag-rgb"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.kurokesu.com\/main\/wp-content\/uploads\/2017\/01\/IMG_8708_r.jpg","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6VSmB-kG","_links":{"self":[{"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/posts\/1282","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/comments?post=1282"}],"version-history":[{"count":33,"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/posts\/1282\/revisions"}],"predecessor-version":[{"id":1333,"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/posts\/1282\/revisions\/1333"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/media\/1298"}],"wp:attachment":[{"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/media?parent=1282"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/categories?post=1282"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kurokesu.com\/main\/wp-json\/wp\/v2\/tags?post=1282"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}