a simple example demonstrating the development of custom "modular things"
This work demonstrates the development, installation and use of a custom "thing" for the "Modular-Things" project.
HelloWorld.mp4
Nota bene: in contrast to the "things" provided by the "Modular Things" project itself, this one has been developed for a Pimoroni Tiny2040 board (which I had on my desk) and a Waveshare RP2040-Zero (which seems to be the cheapest of all small RP2040 boards). Since it uses the built-in RGB LEDs of that board, you may have to adjust the LED output commands in the Arduino "Firmware" shown below in order to make a thing for a different board.
Strange: according to the docs, the built-in WS2812 LED of a Waveshare RP2040-Zero should have a GRB byte order - however, I seem to have an official board (with logo and from a trusted seller) that uses an RGB order. My codes will still use the official GRB order, but some of the boards out there will thus show colors that differ from the expectation. However, this affects the built-in LED only, and everything else should work as expected. Which type of board you have can be easily recognized: just power it up (after uploading any "thing" firmware) and look at the LED: "normal" boards should glow green, others glow red.
Below are instructions for installation and use of the "hello_world" thing - skip whatever does not seem applicable:
- Install Arduino IDE (see https://www.arduino.cc/en/software)
- Install the board "Raspberry Pi Pico/RP2040/RP2350 by Earle F. Philhower, III" using the Arduino "Boards Manager"
- Install "osap by Jake Robert Read" using the Arduino "Library Manager"
- Create a new sketch and rename it to
hello_world - Copy the firmware shown below (or the contents of file hello_world/firmware-RP2040-Zero/hello_world/hello_world.ino if you have a Waveshare RP2040-Zero board) into the sketch editor using the clipboard
- Connect the RP2040 board via USB and select it from the board dropdown in the Arduino IDE
- Compile and upload the sketch
- Install Node.js (see https://nodejs.org/en/)
- Download "modular-things" as a ZIP archive, unpack it, and move it to a location of your choice
- Open a terminal window and navigate to the extracted directory
- run
npm install
- Open the terminal window and navigate to the extracted directory
- copy the "hello_world" directory from this repository and its contents into the
./thingsfolder. Delete thefirmwarefolder for the wrong board and remove the board suffix from the name of the other (you will not damage anything if you use the wrong firmware but this "thing" will simply not work). In the end,./things/hello_worldshould have the following structure:
./things/hello_world/
circuit/
images/
layout.png
schematic.png
preview.png
firmware/
hello_world/
hello_world.ino
software/
hello_world.ts
- Insert the following text into file
./things/_things.jsonafter the first line (i.e., after the opening bracket):
{
"author": "Andreas Rozek",
"name": "hello_world",
"software":"software/hello_world.ts",
"firmware":"firmware/hello_world/hello_world.ino",
"images": [
{
"name": "layout",
"src": "circuit/images/layout.png"
},
{
"name": "schematic",
"src": "circuit/images/schematic.png"
},
{
"name": "preview",
"src": "circuit/images/preview.png"
}
]
},- Insert the following lines into file
./index.ts
import hello_world from "./hello_world/software/hello_world";
e.g., as the last import statementhello_world,
e.g., as the last line in theexport default {block
- (Re)start the server
npm run dev
- Connect the properly prepared RP2040 board to your computer via USB.
- Open the (custom) web environment: http://localhost:3000
- Click on "pair new thing" and select the "thing" you connected before
(the "List of Things" should now display a description of its interface). - Click on "rename" and change the name of your thing to "LEDView" (this is the name used within the application example).
- Copy the following example application into the web editor:
const BlinkDelay = 800 // LED toggles every BlinkDelay milliseconds
let Value = 0
loop(async () => {
Value = (Value === 0 ? 0.1 : 0)
await LEDView.setRGB(0,0,Value)
}, BlinkDelay)- Click on "run (shift + enter)"
(the LED on the RP2040 board should blink now).
In the "Modular Things" terminology, the "firmware" of a thing is an Arduino sketch which implements a thing's functionality on the hardware side. Here is the one for a "hello_world" thing based on a Pimoroni Tiny2040 (please, use the contents of file hello_world/firmware-RP2040-Zero/hello_world/hello_world.ino for a Waveshare RP2040-Zero board instead):
#include <osap.h>
#include <Adafruit_NeoPixel.h>
#define builtin_LED_Pin 16
OSAP_Runtime osap;
OSAP_Gateway_USBSerial serLink(&Serial);
OSAP_Port_DeviceNames namePort("hello_world");
/**** RGB Control ****/
Adafruit_NeoPixel builtin_LED(1, builtin_LED_Pin, NEO_GRB + NEO_KHZ800);
void _setRGB (uint8_t* Data, size_t Length) {
int R = (Length < 2 ? 0 : Data[1]);
int G = (Length < 4 ? 0 : Data[3]);
int B = (Length < 6 ? 0 : Data[5]);
builtin_LED.setPixelColor(0,builtin_LED.Color(R,G,B));
builtin_LED.show();
}
OSAP_Port_Named setRGB("setRGB",_setRGB);
/**** Startup ****/
void setup() {
osap.begin();
builtin_LED.begin();
builtin_LED.setPixelColor(0,builtin_LED.Color(0,16,0));
builtin_LED.show();
}
/**** Operation ****/
void loop() {
osap.loop();
}In the "Modular Things" terminology, the "software" of a thing is its JavaScript interface (which may still include some additional functionality on the software side). Here is the one for the "hello_world" thing:
import Thing from "../../../src/lib/thing"
export default class hello_world extends Thing {
async setRGB (R:number, G:number, B:number):Promise<void> {
const Datagram = new Uint8Array([
255 * Math.max(0,Math.min(R,1)),
255 * Math.max(0,Math.min(G,1)),
255 * Math.max(0,Math.min(B,1)),
])
await this.send('setRGB',Datagram)
}
/**** API Documentation ****/
public api = [{
name: 'setRGB',
args: [
'R: 0 to 1',
'G: 0 to 1',
'B: 0 to 1'
]
}]
}An "application" may be some JavaScript code entered into and run by the "Modular Things" web editor.
Important: as soon as you plan to use custom things, you can no longer use the original web environment found at https://modular-things.com/ but must navigate your browser to http://localhost:3000 (assuming that you use the default port).
Here is an example for an application using the "hello_world" thing:
const BlinkDelay = 800 // LED toggle every BlinkDelay millisecond
let Value = 0
loop(async () => {
Value = (Value === 0 ? 0.1 : 0)
await LEDView.setRGB(0,0,Value)
}, BlinkDelay)