====== Nexmosphere sensors in interactive applications ======
This application note shows how Nexmosphere sensors drive content in Blocks, through eight ready-made example blocks: presence sensing, object detection, push buttons, a touch-free air button, an analog dial, Lift & Learn with a light sensor, an overview of typical applications and a technical dashboard. Each example uses one sensor and one Blocks technique, so it is easy to lift into your own project.
The application note is designed to match Nexmosphere's **DM-XN10 demo board**, which carries a controller and the eight sensors and actuators the examples use, pre-assembled and connected over USB. Plug the board into a PIXILAB Player and every example works as described.
The examples share one design, inspired by Nexmosphere's own application pages. For the drivers themselves, every element and all their properties, see [[blocks:nexmosphere|Nexmosphere Drivers for PIXILAB Blocks]]. For connecting a controller through a serial server, and for programming RFID tags, see the earlier application note [[blocks:app-note:nexmosphere|Use Nexmosphere sensors and actuators with Blocks]].
{{:blocks:app-note:nexmosphere-examples:applications.png?800|}}
===== Hardware requirements =====
The examples use the following hardware:
* A **PIXILAB Player** running the display spot ''Station_1''.
* A **Nexmosphere DM-XN10 demo board**, connected to the player's USB port.
The demo board has its elements on these ports of its controller:
^ Port ^ Element ^ Used by ^
| 1 | XT-B4N6 push buttons | ButtonDemo |
| 2 | XDW-A50 analog interface, with a rotary button | VolumeDemo |
| 3 | Pick-up sensor (reports as XSW-X36) | SensorDashboard |
| 4 | XT-EF30 air gesture sensor | AirButtonDemo |
| 5 | XY-240 time-of-flight sensor | PresenceDemo |
| 6 | XZ-L20 light sensor | LightDemo |
| 7 | XR-DR1 RFID reader, with tags 1, 2 and 3 | ObjectDemo |
| 8 | XW-L56 X-Wave LED strip | The FlashGreen and FlashWhite Tasks |
:!: **Without the demo board, use the same ports.** You can build the same setup from an 8-port Nexmosphere controller, such as an XN-185, and separate elements. If you connect the devices manually, make sure each one goes to the same port as on the demo board. The driver names each element after its type, model and port, for instance ''TOF_XY240_5'', and the blocks and Tasks bind to those names, so an element on another port gets another name and the examples stop responding to it. If you must use other ports, name the elements in the driver options, as described in the [[blocks:nexmosphere|driver documentation]], and update the paths in the blocks and Tasks.
===== Installation =====
Here's a PIXILAB-Blocks-root folder containing everything you need for this application:
{{ :blocks:app-note:nexmosphere_v2:pixilab-blocks-root.zip |Download this ZIP file and unpack it}}
then follow the instructions in the [[blocks:app-note:start|general setup section]].
Once you've done the general setup and pointed your Blocks server to this root folder:
- Connect the DM-XN10 demo board to the PIXILAB Player's USB port and power it up. If you're using your own controller instead, connect the elements to the ports listed above first.
- Start Blocks and open the editor.
- Check that the player is connected as the display spot ''Station_1''.
- Check that the Network Device ''Sensors_Station1'' is online. It is a **Serial** device on ''Station_1'', using the ''NexmosphereXN180'' driver at 115200 baud.
- Assign the block ''Nexmophere/SensorDashboard'' to ''Station_1''. Every card should show live values: press a button, wave at the time-of-flight sensor, place a tag.
- Then assign any of the other example blocks to ''Station_1'' to try it.
:!: The Tasks address the spot by name, ''Spot.Station_1''. If your display spot has another name, update the Tasks, and the ''ThisSpotPath'' parameter of the blocks that have one.
===== Try it =====
^ Block ^ Sensor ^ Try this ^ What happens ^
| ''Nexmophere/Applications'' | none | Tap the tabs, or swipe | Three pages: presence sensing, Lift & Learn and personalised storytelling. |
| ''Nexmophere/PresenceDemo'' | XY-240 time of flight | Step up close to the sensor | "Step closer" gives way to the presence content. 15 s after the last touch, the screen returns. |
| ''Nexmophere/ObjectDemo'' | XR-DR1 RFID | Place tag 1, 2 or 3 on the reader, then lift it | The page for that box appears, and lifting the tag brings back "Place a box". |
| ''Nexmophere/ButtonDemo'' | XT-B4N6 buttons | Press button 1 or button 4 | Content 1 or content 2 appears, and the screen returns after 15 s. |
| ''Nexmophere/AirButtonDemo'' | XT-EF30 air gesture | Hold a hand above the sensor | A 10 s film plays, and the screen returns to "Hover here" when it ends. |
| ''Nexmophere/VolumeDemo'' | XDW-A50 analog | Turn the dial | A song plays with its lyrics as subtitles on the screen in the picture. The meter, the slider and the loudness follow the dial. |
| ''Nexmophere/LightDemo'' | XZ-L20 light | Lift the product off the sensor | The product's story appears, and putting it back returns to "Pick one up". |
| ''Nexmophere/SensorDashboard'' | all | Use any sensor | One card per element, with its live values. |
{{:blocks:app-note:nexmosphere-examples:presencedemo.png?400|}} {{:blocks:app-note:nexmosphere-examples:objectdemo.png?400|}}
{{:blocks:app-note:nexmosphere-examples:volumedemo.png?400|}} {{:blocks:app-note:nexmosphere-examples:sensordashboard.png?400|}}
===== How it is done =====
The examples get from a sensor to content in three ways:
* **A Task sets a property**, usually ''Spot.Station_1.active''. An **Attractor** block shows its first child, the active page, while the spot is active, and its second child, the attract page, when it is not.
* **A behaviour reacts to the sensor directly**, with no Task. //Reveal// brings its block forward when the property becomes true, //Navigate// goes to the child numbered by the property, and //Volume// sets the volume from it.
* **A binding shows the value**: a Bar, a Slider, an Indicator, or a text with ''{$1}''.
==== Presence sensing ====
''PresenceDemo'' is an Attractor. The Task ''OnPresence'' triggers when ''triggerOn1'' of the time-of-flight sensor becomes true, which means someone is in the nearest zone. It then sets ''Spot.Station_1.active'' to true, waking the Attractor.
The Task only runs while this block is on the spot, thanks to its trigger condition:
Spot.Station_1.block === "Nexmophere/PresenceDemo"
The Attractor returns to the attract page 15 s after the last touch, or at once when "Back to start" is tapped. A tap on the attract page also wakes it, which is handy without a sensor. Use another ''triggerOnN'' for a greater distance: zone 1 is nearest, zone 10 is furthest.
==== Object detection ====
''ObjectDemo'' is a Book with four pages: "Place a box", then the pages for box 1, 2 and 3. A //Navigate// behaviour on the Book follows the realm variable ''wantedBox'': 0 shows the first page, 1 to 3 the box pages.
The Task ''OnRFID'' triggers when ''isPlaced'' of the RFID reader changes, and only while ObjectDemo is shown. A placed tag copies its number into the variable; a lifted one sets it back to 0:
if (trigger) set wantedBox = Network.Sensors_Station1.element.RFID_XRDR1_7.tagNumber
if (!trigger) set wantedBox = 0
Program tags with the numbers 1, 2 and 3 for the three boxes. The earlier [[blocks:app-note:nexmosphere|application note]] shows how.
==== Push buttons ====
''ButtonDemo'' is an Attractor whose active page holds a Book with two contents. Each content has a //Reveal// behaviour, bound to ''button1'' and ''button4'' of the XT-B4N6 respectively. A press brings that content forward. No Task is needed.
The two blue buttons on the screen do the same for a demonstration without the hardware. The contents in this example are placeholder pictures: replace them with your own media.
==== Air button ====
''AirButtonDemo'' is an Attractor whose active page carries a //Reveal// behaviour bound to ''gesture'' of the XT-EF30. A hand held above the sensor brings the active page forward, and it plays a 10 second film.
The Attractor's //Deactivate when playback ends// setting returns it to the attract page as the film ends. A 30 second timeout is only a backstop.
==== Analog control and synchronised lyrics ====
''VolumeDemo'' reads the XDW-A50, whose value runs from 0 to 20 with the default settings.
* The **Slider** and the level **meter**, a Bar masked into twelve steps, are bound to the analog value with the range 0 to 20, so both follow the dial.
* The **loudness** follows the dial too, in either of two ways. A //Volume// behaviour on the clip sets its volume from the value, with a scale factor of 0.2. Or the Task ''OnAnalog'' sets the spot's master volume, scaling the value to 0-1:
Spot.Station_1.volume = trigger/20
The song comes with its lyrics as an ''.srt'' file, shown by a Subtitle block over the picture's TV screen. The clip and the Subtitle block are wrapped in a **Synchronizer** with //Local sync// set, so the lyrics keep time with the music, also when the song loops. The clip itself does not loop, since the Synchronizer does, and the Subtitle block has //Locally Synchronised// ticked. See the [[blocks:app-note:subtitles|Subtitles application note]] for more on this technique.
==== Lift & Learn with a light sensor ====
''LightDemo'' is an Attractor. The product stands on the XZ-L20, and lifting it lets light reach the sensor. The Task ''OnLight'' triggers on every change of ''light'' and sets ''Spot.Station_1.active'' to the value, so any light wakes the screen and darkness lets it return:
Spot.Station_1.active = trigger
Put the product back, tap "Back to start", or wait 60 s, and the screen returns. The sensor's trigger values can be adjusted with its ''sendSettings()'' callable.
==== Sensor dashboard ====
''SensorDashboard'' has no logic at all: each card binds read-only to one element, with lamps for the true/false properties, numbers and texts for the rest, and a bar for the proximity zone. It is the quickest way to check the hardware, and to see what values a sensor sends before you write a Task for it.
{{:blocks:app-note:nexmosphere-examples:sensordashboard.png?800|}}
===== The Tasks =====
All the Tasks are in the realm ''Nexmosphere'', group ''ApplicationNote''.
^ Task ^ Trigger ^ Condition ^ What it does ^
| ''OnPresence'' | ''TOF_XY240_5.triggerOn1'' becomes true | PresenceDemo is on the spot | ''Spot.Station_1.active = true'' |
| ''OnRFID'' | ''RFID_XRDR1_7.isPlaced'' changes | ObjectDemo is on the spot | Sets the realm variable ''wantedBox'' to the tag number, or 0 |
| ''OnLight'' | ''Light_XZL20_6.light'' changes | none | ''Spot.Station_1.active = trigger'' |
| ''OnAnalog'' | ''AnalogIn_XDWA50_2.value'' changes | none | ''Spot.Station_1.volume = trigger/20'' |
| ''FlashGreen'', ''FlashWhite'' | none | | Flash the X-Wave LED strip briefly, green or white |
**Limit a Task to its block** with a condition such as ''Spot.Station_1.block === "Nexmophere/ObjectDemo"''. Several examples use the same spot, and without the condition every Task would react whatever is on the screen.
**Give feedback with light.** ''FlashGreen'' and ''FlashWhite'' flash the X-Wave strip to full brightness, wait 0.3 s and fade it out over a second, using the element's ''setSingleRamp(brightness, color, ramp)'' callable, whose ramp time counts in tenths of a second. Run one from another Task, for example when a tag is placed, to show the visitor that the sensor saw them.
===== Look and feel =====
The examples share one design: a header band, light Roboto text, the blue accent colour, and pictures drawn for each application. Each block carries its own ''style.css'' and the Roboto font in its ''media'' folder, so it looks the same on any player, whatever fonts are installed there. Text blocks are styled by CSS classes rather than inline formatting, so they remain editable in the editor.
To reuse a design in your own block, copy the block, change its texts and pictures, and keep its ''style.css''.
===== Other applications =====
The same patterns go a long way beyond these examples:
* Replace the time-of-flight sensor with an XY-116 proximity sensor, or an XY-320 motion sensor, to wake an Attractor in the same way.
* Use a pick-up sensor (''pickup'') instead of the light sensor for Lift & Learn, with one product per sensor.
* Combine RFID with languages: a tag per language, and a TagSelector, selects the subtitles a visitor sees.
* Drive DMX lights or the controller's built-in LED outputs from the same Tasks that change the content.