# 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#registers) 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="/files/oK6j4Hs28nPfBfi0l1Kb" 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)

**Example:**

<figure><img src="/files/tgDFnxIkjKw0Hu4F9Nvh" 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="/files/HNH4yNBP2hVYoxpZRBAG" 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)

**Example:**

<figure><img src="/files/GEYLIlPcU3YQBQLUrrCw" alt=""><figcaption><p>Receive brightness value from dashboard and set LED accordingly</p></figcaption></figure>

## digital read

<div align="left"><figure><img src="/files/a3fqTmIV9YuVUm1myFHC" 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="/files/QSB5kyZVrA2VAWBMf1kc" alt=""><figcaption><p>Read switch state and push event when changed</p></figcaption></figure>

## digital write

<div align="left"><figure><img src="/files/kDYr0PrnKnJ8blKd1CZe" 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="/files/U9PWVuo57LXOQ5uby8fC" alt=""><figcaption><p>Check for event and control LED state</p></figcaption></figure>

## button clicked

<div align="left"><figure><img src="/files/3DTLjbyD22wLVJXl1DON" 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 digital input register index

**Returns:**

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

**Example:**

<figure><img src="/files/x1405XIewileOBVv0kLf" alt=""><figcaption><p>Toggle LED state on button click</p></figcaption></figure>

## user primitive (template)

<div align="left"><figure><img src="/files/Y5Eg7cUvKFhhOj6mMrpY" 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="/files/FRBn67XTWq47Av9dToMl" 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="/files/ddoO4tOqjfV0eN1O0Gs1" alt=""><figcaption><p>Custom LED strip control</p></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.uniot.io/platform/sandbox/visual-editor/primitives.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
