Neopixel Matrix Test with Obniz Boards

This contribution contains a few simple Node-RED flows to control an obniz board with an attached Neopixel 16x16 RGB matrix - although they may easily be adapted to other geometries of chained WS2812 RGB LEDs (but only up to a length of 85 LEDs because of restrictions in the obniz board)

flows and documentation may also be found on GitHub and have been published here for easier lookup only

Prerequisites

In order to run these examples you will need

  • a working Node-RED instance,
  • node-red-contrib-obniz - which installs some nodes to communicate with obniz boards,
  • an obniz board,
  • Internet access (because of the obniz board) and
  • any kind of WS2812 RGB LED or string

Instructions

Once you have all the components together, you will have to

  • start up (and configure) the obniz board
  • connect the WS2812 LED string
  • import these flows
  • configure the obniz nodes (i.e., enter the credentials of your board) and
  • start the flows as desired

flows

Start-up the Obniz Board

After powering up the obniz board, you will have set-up a Wifi connection (as desribed in the board's instruction manual) and - once the board has established a connection to its server - configure board access in the obniz developer's console: simply

  • press "+ Add device"
  • choose your board type
  • press "I'm ready" and
  • type in your obniz id and press "Next"

Right now, everybody may access your obniz board just by providing its id. It is therefore highly recommended to generate an "Access Token" in the developer's console. Such a token does not automatically expire but remains until explicitly deleted or renewed. As soon as a token has been assigned, board access is only granted if the proper token is provided along with the request (see below)

Connect the WS2812 LED String

In this example, the WS2812 "data in" wire is connected to pin 4 of the obniz board. If you prefer a different pin, you may do so by modifying the "obniz function" nodes accordingly.

The LED's Vcc and GND wires should be directly connected to your power supply.

Import Flows

If not already done, you should install the obniz nodes from node-red-contrib-obniz as described on that page.

Now, you may import the described flows either from below or directly from the GitHub repository. Just select the whole text, copy it into the clipboard, then choose "Import" from the Node_RED Editor menu, copy the clipboard contents, press "Import" and drag the flows to a place of your choice.

Configure Obniz Nodes

Once the flows have been imported, the obniz nodes have to be configured: you have to provide the serial id of your board and the access key you generated in the obniz developers console. "Instructions" can be found on the obniz node page - as usual, there are in a horrible shape, but fortunately, it turns out not to be too difficult

Run desired Flows

This contribution contains four different flows. Because of how the obniz board works, they have to share the configured wiring - once set up, it will be stored in the flow context and reused by any other flow (which is why it has to be reset automatically upon re-deployment)

  • x-axis
    this flow draws a "x-axis" by lighting the LEDs 0, 1, 2 up to 15
  • y-axis
    this flow draws a "y-axis" by lighting the LEDs 0, 16, 32 and so on - this is useful because matrices are usually wired in a serpentine manner
  • test of 5 rows
    the initial idea was to write a short function test to see if all matrix LEDs work as intended. This flow tests 5 rows of the connected matrix (because of restrictions in the obniz board) row-wise and alternately in red, green and blue
  • clear matrix
    WS2812 LEDs are very bright and may disturb when lighting - this flow therefore switches all LEDs off
[{"id":"fada2e3557c32725","type":"comment","z":"a48cb54775e4adb7","name":"Neopixel 16x16 Matrix","info":"","x":1440,"y":40,"wires":[]},{"id":"cb0394a7f5d9e05c","type":"inject","z":"a48cb54775e4adb7","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":1570,"y":160,"wires":[["9fc8d1f8d76c39cb"]]},{"id":"2d567467b5ba88ba","type":"comment","z":"a48cb54775e4adb7","name":"x-axis","info":"","x":1390,"y":160,"wires":[]},{"id":"9fc8d1f8d76c39cb","type":"obniz-function","z":"a48cb54775e4adb7","obniz":"da56dbaeec07a74f","name":"","code":"obniz.display.clear()\nobniz.display.print(\"Neopixel Matrix x-axis\")\n\nlet Matrix = flow.get('obniz-neopixel-matrix')\nif (Matrix == null) {\n  Matrix = obniz.wired('WS2812',{ gnd:11, vcc:7, din:4 })\n  flow.set('obniz-neopixel-matrix',Matrix)\n}\n\nlet red = [0xFF,0x00,0x00]\nMatrix.rgbs([\n  red,red,red,red,red,red,red,red,red,red,red,red,red,red,red,red\n])\n","x":1740,"y":160,"wires":[[]]},{"id":"acd7279111d103d6","type":"inject","z":"a48cb54775e4adb7","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":1570,"y":220,"wires":[["480919a220665f54"]]},{"id":"7ddee3dd6120875f","type":"comment","z":"a48cb54775e4adb7","name":"y-axis","info":"","x":1390,"y":220,"wires":[]},{"id":"480919a220665f54","type":"obniz-function","z":"a48cb54775e4adb7","obniz":"da56dbaeec07a74f","name":"","code":"obniz.display.clear()\nobniz.display.print(\"Neopixel Matrix y-axis\")\n\nlet Matrix = flow.get('obniz-neopixel-matrix')\nif (Matrix == null) {\n  Matrix = obniz.wired('WS2812',{ gnd:11, vcc:7, din:4 })\n  flow.set('obniz-neopixel-matrix',Matrix)\n}\n\nlet dark  = [0x00,0x00,0x00]\nlet green = [0x00,0xFF,0x00]\n\nlet LEDs = []\n  for (let i = 0; i < 5; i++) { // due to max. chain length\n    LEDs.push(green)\n    for (let j = 0; j < 15; j++) { LEDs.push(dark) }\n  }\nMatrix.rgbs(LEDs)\n","x":1740,"y":220,"wires":[[]]},{"id":"46af354dc9470b98","type":"comment","z":"a48cb54775e4adb7","name":"Warning: max. chain length = 85","info":"","x":1710,"y":40,"wires":[]},{"id":"1f49438e80ac85a2","type":"comment","z":"a48cb54775e4adb7","name":"test of 5 rows","info":"","x":1410,"y":280,"wires":[]},{"id":"5da4b41743b97936","type":"inject","z":"a48cb54775e4adb7","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":1570,"y":280,"wires":[["afa324f52ed8c0fb"]]},{"id":"afa324f52ed8c0fb","type":"obniz-function","z":"a48cb54775e4adb7","obniz":"da56dbaeec07a74f","name":"","code":"  obniz.display.clear()\n  obniz.display.print(\"Neopixel Matrix Test\")\n  \n  let Matrix = flow.get('obniz-neopixel-matrix')\n  if (Matrix == null) {\n    Matrix = obniz.wired('WS2812',{ gnd:11, vcc:7, din:4 })\n    flow.set('obniz-neopixel-matrix',Matrix)\n  }\n  \n  let dark  = [0x00,0x00,0x00]\n  let red   = [0xFF,0x00,0x00]\n  let green = [0x00,0xFF,0x00]\n  let blue  = [0x00,0x00,0xFF]\n  \n  let LEDs = []\n\n  function clearUntilRow (Row) {\n    LEDs = []\n    for (let i = 0; i < Row; i++) {\n      fillNextRowWith(dark)\n    }\n  }\n  \n  function fillNextRowWith (Value) {\n    for (let i = 0; i < 16; i++) { LEDs.push(Value) }\n  }\n  \n  function testRowWith (Row, Value) {\n    clearUntilRow(Row)\n    fillNextRowWith(Value)\n    Matrix.rgbs(LEDs)\n  }\n\n  let NumberOfTests = 5 * 3                        // five rows, each with R,G,B\n\n  let currentTest = -1\n    function runNextTest () {\n      currentTest += 1\n      if (currentTest >= NumberOfTests) { return }\n      \n      let currentRow   = Math.floor(currentTest / 3)\n      let currentValue = currentTest % 3\n      switch (currentValue) {\n        case 0: testRowWith(currentRow,red);  break\n        case 1: testRowWith(currentRow,green); break\n        case 2: testRowWith(currentRow,blue);  break\n      }\n      \n      setTimeout(runNextTest,4000)\n    }\n  runNextTest()","x":1740,"y":280,"wires":[[]]},{"id":"fdde153e05cc894b","type":"inject","z":"a48cb54775e4adb7","name":"on Startup","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"date","x":1430,"y":100,"wires":[["290901ac912741bf"]]},{"id":"290901ac912741bf","type":"change","z":"a48cb54775e4adb7","name":"reset Neopixel wiring","rules":[{"t":"delete","p":"obniz-neopixel-matrix","pt":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":1640,"y":100,"wires":[["788e471787891f87"]]},{"id":"788e471787891f87","type":"debug","z":"a48cb54775e4adb7","name":"show","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"'wiring removed'","statusType":"jsonata","x":1830,"y":100,"wires":[]},{"id":"b24ee282607acd77","type":"comment","z":"a48cb54775e4adb7","name":"clear matrix","info":"","x":1410,"y":340,"wires":[]},{"id":"afd70788b31d717f","type":"inject","z":"a48cb54775e4adb7","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":1570,"y":340,"wires":[["7abd1980a0fb7725"]]},{"id":"7abd1980a0fb7725","type":"obniz-function","z":"a48cb54775e4adb7","obniz":"da56dbaeec07a74f","name":"","code":"  obniz.display.clear()\n  obniz.display.print(\"Neopixel Matrix Test\")\n\n  let Matrix = flow.get('obniz-neopixel-matrix')\n  if (Matrix == null) {\n    Matrix = obniz.wired('WS2812',{ gnd:11, vcc:7, din:4 })\n    flow.set('obniz-neopixel-matrix',Matrix)\n  }\n\n  let dark = [0x00,0x00,0x00]\n\n  let LEDs = []\n    for (let i = 0; i < 85; i++) { LEDs.push(dark) }\n  Matrix.rgbs(LEDs)\n","x":1740,"y":340,"wires":[[]]},{"id":"da56dbaeec07a74f","type":"obniz","obnizId":"","deviceType":"obnizboard","name":"","accessToken":"","code":""}]

Flow Info

Created 2 years, 8 months ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • change (x1)
  • comment (x6)
  • debug (x1)
  • inject (x5)
Other
  • obniz (x1)
  • obniz-function (x4)

Tags

  • obniz
  • ws2812
  • led
  • matrix
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option