Skip to content

Quick Start

Kenneth Kang edited this page Jan 29, 2020 · 13 revisions

This guide is intended to help users with the typical usage of Loom.

Table of Contents

Setup

If you haven't already, set up Arduino following our following guides:

Run an Example

Start by compiling one of the Loom examples (File > Examples > Loom >) to ensure that it compiles. If not, review the guides linked in the above section.

Usage

Configuration

The configuration of a device is specified via a JSON configuration. In examples, this takes the form of a config.h file. See our JsonConfig on how you can define a configuration. Note that there are a few different ways to define the configuration:

  • In .ino file
  • External file, compact
  • External file, pretty

The external .h file options are preferred, either of these two versions is fine, but the "pretty" format takes up more space, so for deployments, prefer "compact".

See the documentation or source code (.h files) for valid module parameter.

For a more in-depth explanation of using and building the configuration see this page.

Including configuration

As shown in the example, include a configuration like so:

const char* json_config = 
#include "json_config.h"
;

Note that these 3 lines cannot be shortened into one

Configurator Interface

Work is being done to build an interface that allows users to graphically specify a configuration.h file that you can place in the sketch folder. See Loom Configurator and Loomify for the development of this web app.

Loom Manager

The LoomManager automates much of the operation of a Loom device, preventing you from having to individually manage each module. The most important features of the Manager are covered here.

Parsing Configuration

In order to use a Json configuration, it needs to be parsed by a LoomManager. For each component in the configuration, the manager will create a module according to the provided settings. Pass the configuration to the manager in setup()) as follows (see bottom of this readme for full program):

Manager.parse_config(json_config);

Print Configuration

If you would like to see the configuration of the device, you can print it with:

Manager.print_config();

Measure Data

The manager provides a measure() method to automate the process of measuring data of all sensor type modules. The method does not take an argument or return anything.

Manager.measure();

Package Data

Packaging data entails copying the measured data into a Json object. Non-sensor type modules may also package data to the Json, depending on package_verbosity settings. Use either of the following formats to extract the packaged data from the manager.

JsonObject data1 = Manager.package();
// or
JsonObject data2;
Manager.package(data2);

Note that you can also get the current state of the LoomManagers internal Json object at any time (without updating the data that is packaged) with JsonObject internal_json (bool clear=true), which can be used as follows. By default, this operation empties the Json object (so you can use it), if you do not want to clear the data, send an argument false to the method.

JsonObject notClearedJson = Manager.internal_json(false);

JsonObject clearedJson = Manager.internal_json();

Append to Data Json

After package data, you can add non-Loom data to the Json data package with template<typename T> bool add_data(const char* module, const char* key, T val).

Example:

Manager.add_data("exampleModule", "key", 12345);

You can also add to a Loom module's section of the data object. If the provided module name matches a component already in the data package, your data key-value pair will be added to that component.

Print Json object

If you want to print the Json object to the Serial monitor, the ArduinoJson library provides built-in functionality to do so, formatting it to be easily readable.

JsonObject toPrint;
serializeJsonPretty(toPrint, Serial);

Publish to Internet

Command Routing

Some modules support executing commands based on a command defined in a Json object. Rather than send the command directly to the intended module, you can just send it to the LoomManager, which will determine which module it goes to and forward the command to it.

JsonObject command;
Manager.cmd_route(command);

For more details on executing commands and how the Json of command is structured, see the Executing Commands page.

More

See the LoomManager Documentation for all avaible LoomManager methods.

Module

All modules within Loom inherit from LoomModule and have access to any public LoomModule methods. The same applies to the rest of the inheritance hierarchy. For example, any sensor (directly or indirectly) inherits from LoomSensor and thus has access to LoomSensor public methods. Inherited methods are shown in the documentation.

The methods of modules managed by a LoomManager can be accessed with dot syntax.

For example, if you wanted to access a relay module being managed by a LoomManager, you can access the LoomRelay module via:

// Manager is a LoomManager
Manager.Relay();

The above command does not actually do anything, but it gives you access to the methods of the LoomRelay. For example, to set the relay, LoomRelay has a method void set(bool enable), which we can access like:

Manager.Relay().set(true);

You can also set a variable to the return of a method like:

bool moduleActive = Manager.Relay().get_active();

If you have multiple of a given type of module, you can access them via index (zero indexed):

Manager.Relay(2); // get third relay

Does not exist: If any time you try to access a module that does not exist, rather than receiving a null pointer, you will just get a LoomModuleStub that will simply print out an error for any method you try to run on it.

Setting module access to a variable: Note that while you can technically set the module accessed to a variable, it is recommended against. For example:

Loom_Relay relay = Manager.Relay();
// relay and Manger.Relay() now refer to different objects

In some cases, behavior might work fine but as the two objects are different, changing one will not change the other.

Available Methods

See the Documentation for available methods of individual modules.

Secondary Managers

Loom has a few secondary managers that are LoomModules specialized to managing features more general than an individual hardware component. These currently include:

  • Interrupt manager
  • Sleep manager
  • Multiplexer

See the Secondary Managers wiki page for details on their usage.

Printing to Serial

Loom provides a few macros (LPrint, LPrintln, LPrintlnAll) to simplify printing to the Serial monitor. All three take arbitrary many arguments and the arguments can be of any type. This avoids the need for a series of Serial.prints.

LPrint: Print variable number of arguments (no newline)

LPrint("abc", 123);
// produces:
// abc123

LPrintln: Print variable number of arguments with a newline after the last element

LPrintln("abc", 123);
// produces:
// abc123

LPrintlnAll: Print variable number of arguments with a newline after each element

LPrintlnAll(1, 2.34, true, "string", String("another string"));
// produces:
// 1
// 2.34
// 1
// string
// another string

Documentation

Wiki for general documentation not contained in GitHub readmes

Doxygen generated documentation for documentation of the code and how to use

Contribute to Loom

Is there hardware support or other feature you would like to add to Loom? Follow our guide to contributing to Loom

Basic Example

The code for this example can also be found on GitHub or via the Arduino IDE (File > Examples > Loom > Basic) if you have Loom installed.

This is a basic example of specifying a configuration, including it, using the manager, parsing a config, and printing out analog data readings.

#include <Loom.h>

// Include configuration
const char* json_config = 
#include "config.h"
;

// Set enabled modules
LoomFactory<
	Enable::Internet::Disabled,
	Enable::Sensors::Enabled,
	Enable::Radios::Disabled,
	Enable::Actuators::Disabled,
	Enable::Max::Disabled
> ModuleFactory{};

LoomManager Loom{ &ModuleFactory };

void setup() 
{ 
	Loom.begin_LED();
	Loom.begin_serial(true);
	Loom.parse_config(json_config);
	Loom.print_config();

	LPrintln("\n ** Setup Complete ** ");
}

void loop() 
{
	Loom.measure();
	Loom.package();
	Loom.display_data();
	Loom.pause();
}

Tips

Many of the following tips can also be found in more detail on Adafruit's [Using with Arduino IDE](Using with Arduino IDE) guide.

  • Setting the IDE to verbose upload may be useful to make sure the IDE is searching for and then uploading to the board:

    • PC: File > Preferences
    • Mac: Arduino > Preferences
    • Show Verbose output during: check the upload box
  • Make sure the board profile is correct:

    • Select: Tools > Board > Adafruit Feather M0
  • Make sure your board is selected:

    • Connect a USB Micro Cable between your Feather M0 and computer USB port, then select your device via:
    • PC: Select: Tools > Port > COMx
    • Mac: Select: Tools > Port > Feather M0
  • Open the Serial Monitor to view any output the board is printing:

    • Click magnifying glass icon or Tools > Serial Monitor
  • If the board seems to be frozen, the IDE says "Uploading to I\O board", or if the last program involved sleep, double-tapping the reset button will