Sabatino Autorino
Published © MIT

Ship a motion-sensing product in days, not years

A sealed ±32 g edge-AI node plus the whole stack — firmware, OTA, cloud, API, dashboards. You build only what makes your product yours.

IntermediateWork in progress1 hour20
Ship a motion-sensing product in days, not years

Things used in this project

Hardware components

nRF54L15
Nordic Semiconductor nRF54L15
MCU + BLE 5 Long Range
×1
LSM6DSV32X
±32 g IMU with Machine Learning Core
×1
LIS3MDL
magnetometer
×1
LPS22HH
barometer
×1
BQ25100
Li-Po charger
×1
MAX17048
fuel gauge
×1
TPS62840
buck converter
×1

Software apps and online services

Zephyr RTOS
Zephyr Project Zephyr RTOS
meltinode lab

Story

Read more

Schematics

Block diagram — from the sensor to your app

How MeltiNode is built: the node (±32 g IMU with on-sensor ML, nRF54L15, BLE Long Range, Qi charging), the gateway (phone, Lab or hub, which also pushes OTA updates), and the cloud that is already built — Lab, REST API, live stream, webhooks and dashboards — so you only build your own app on top.

Code

Read your nodes from the API (Python)

Python
Pull the latest metrics and the live event stream of a cluster from the MeltiNode API.
"""MeltiNode quickstart: read your nodes' data from the API.

1. In the Lab (https://www.meltinode.com/lab) create a project and a cluster,
   then open the "Output" window: copy the cluster address and its token.
2. Run with a virtual node or your phone streaming in the Lab:
       MELTINODE_CLUSTER=my-cluster MELTINODE_TOKEN=snc_... python meltinode_quickstart.py
"""
import json
import os

import requests

CLUSTER = os.environ["MELTINODE_CLUSTER"]
TOKEN = os.environ["MELTINODE_TOKEN"]
BASE = f"https://api.meltinode.com/v1/clusters/{CLUSTER}"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}

# Who is in the cluster (athletes, patients, workers, machines...)
targets = requests.get(f"{BASE}/targets", headers=HEADERS, timeout=10).json()
print("targets:", json.dumps(targets, indent=2))

# The latest JSON for every target: the metrics your models produce
latest = requests.get(f"{BASE}/latest", headers=HEADERS, timeout=10).json()
print("latest:", json.dumps(latest, indent=2))

# Live events as they happen (Server-Sent Events): punches, falls, lifts...
with requests.get(f"{BASE}/events/stream", headers=HEADERS, stream=True, timeout=(10, None)) as r:
    for line in r.iter_lines(decode_unicode=True):
        if line and line.startswith("data:"):
            event = json.loads(line[5:])
            print("event:", event)

Credits

Sabatino Autorino
1 project • 0 followers

Comments