> For the complete documentation index, see [llms.txt](https://docs.uniot.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.uniot.io/platform/sandbox/visual-editor/primitives.md).

# Primitives

Primitive blocks provide direct access to device hardware. Use these blocks to read sensors, control digital and analog outputs, handle button inputs, and create custom hardware interactions.

## Understanding Registers

Primitives use [register](/general-concepts/primitives.md#the-register-system) indices instead of physical pin numbers. The register system organizes pins into categories (digital input/output, analog input/output) and assigns each an index. View your device's pin-to-register mapping in the Registers tab on the Uniot Platform.

## Return Values in Primitives

Primitives can either return a value or perform an action without returning meaningful data. The visual blocks for default primitives (like `analog read`, `digital read`, etc.) are predefined and correctly reflect whether they return values or not.

For user-defined primitives, the visual editor cannot automatically determine whether a primitive should return a value or just perform an action. Since primitives are C++ functions called by the UniotLisp Interpreter, every function must return something—even action-only primitives return a boolean value. Therefore, user primitive blocks are rendered with a return value by default. If your primitive doesn't need to return a meaningful value, you can disable the return value field in the block configuration.

## analog read

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-2bd9d886c56b6e028046db07df744e59bd43fa9b%2Fprimitives_analog_read.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

Reads an analog value from the specified register. Use this for sensors that output variable voltage levels.

**Parameters:**

* **Register** (Number): The analog input register index

**Returns:**

* **Number**: Value between 0-1023 (10-bit ADC resolution, the same on every chip)

**Example:**

<figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-5d97e0ab5b2792663a688fbed1f86808cbfdf122%2Fprimitives_analog_read_example.svg?alt=media" alt=""><figcaption><p>Check light level and push event if it's too low</p></figcaption></figure>

## analog write

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-fa3a10df87b3c6b257d4202726e1178ff12c1774%2Fprimitives_analog_write.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

Writes an analog (PWM) value to the specified register. Use this to control LED brightness, motor speed, or other variable outputs.

**Parameters:**

* **Register** (Number): The analog output register index
* **Value** (Number): Value between 0-1023 (PWM duty cycle)

**Returns:**

* **Number**: The value written

**Example:**

<figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-d696917a0cf6490450d3d2ee35e0586cafcfe05e%2Fprimitives_analog_write_example.svg?alt=media" alt=""><figcaption><p>Receive brightness value from dashboard and set LED accordingly</p></figcaption></figure>

## digital read

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-6b261e3d9fe9e0fd59ac5415993c0b83bcec5e08%2Fprimitives_digital_read.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

Reads the digital state from the specified register (HIGH or LOW).

**Parameters:**

* **Register** (Number): The digital input register index

**Returns:**

* **Boolean**: `#t` for HIGH, `()` for LOW

**Example:**

<figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-ffedd00eadb0c25e6aefa2d685c05f49b743d3c9%2Fprimitives_digital_read_example.svg?alt=media" alt=""><figcaption><p>Read switch state and push event when changed</p></figcaption></figure>

## digital write

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-c547ff6a15ce9542496837cdf49f4e83c68e7214%2Fprimitives_digital_write.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

Sets a digital register to HIGH or LOW. Use this to control LEDs, relays, or other on/off outputs.

**Parameters:**

* **Register** (Number): The digital output register index
* **Value** (Boolean): `#t` for HIGH, `()` for LOW

**Example:**

<figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-19c1818af99e1ac51b56caf6ebd9cca3be939838%2Fprimitives_digital_write_example.svg?alt=media" alt=""><figcaption><p>Check for event and control LED state</p></figcaption></figure>

## button clicked

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-a4cb80877adefe123dcef95a57fd5c2f87d73cc1%2Fprimitives_button_clicked.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

Detects button press events on the specified register. Returns true when a press-and-release cycle is detected, then resets until the next click.

**Parameters:**

* **Register** (Number): The button's index in the `bclicked` register, in registration order. The WiFi reset button is usually `0`; see [Button Clicked](/general-concepts/primitives.md#available-built-in-primitives)

**Returns:**

* **Boolean**: `#t` if clicked since last check, `()` otherwise

**Example:**

<figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-271a832f810ce4ccebf6dc072d43bb058a9b4272%2Fprimitives_button_clicked_example.svg?alt=media" alt=""><figcaption><p>Toggle LED state on button click</p></figcaption></figure>

## user primitive (template)

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-9ab9ba1c41e43cb39d898cd576f5c5aecca79ae2%2Fprimitives_user_primitive.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

Creates a custom primitive definition that you'll implement in your firmware. Click the gear icon to configure parameters and return type.

**Configuration:**

* **Primitive Name**: Unique identifier for your custom primitive
* **Parameters**: Define input values the primitive accepts
* **Return Type**: Configure what type of value it returns (boolean by default, or none for action-only primitives)

{% hint style="info" %}
**Note on return values**: Since primitives are C++ functions called by the UniotLisp Interpreter, every function must return a value. If your primitive performs an action without needing to return a meaningful value, it should still return a boolean. The visual block is rendered with a return value by default. If you don't need to use the return value, you have to disable the corresponding field in the block configuration.
{% endhint %}

**Use cases**: Creating custom sensor drivers, protocol handlers, complex hardware control, or specialized operations not covered by standard primitives.

## user primitive (autogenerated)

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-ae85f9c69be1025eed64a633b76422a8135a74a6%2Fprimitives_user_primitive_auto.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

Calls a custom primitive already defined in your device firmware. These blocks are automatically generated based on primitives registered in your firmware code.

**Parameters:**

* **Arguments**: Values matching the primitive's defined parameters

**Returns:**

* **Type varies**: Depends on how the primitive was defined in firmware

{% hint style="info" %}
**Note on return values**: Since the visual editor cannot determine whether a user primitive is intended to return a value or just perform an action, autogenerated blocks are rendered with a return value by default. This is because all C++ functions must return something—even action-only primitives return a boolean value. If your primitive doesn't need to return a meaningful value, you have to disable the return value field in the block configuration.
{% endhint %}

**Example:**

<figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-934b1880b6dfc783d57c145b07fe14bc4f21d704%2Fprimitives_user_primitive_auto_example.svg?alt=media" alt=""><figcaption><p>Custom LED strip control</p></figcaption></figure>
