Primitives
Last updated
Last updated
Primitives are building blocks that bridge the gap between and hardware interactions. They serve as functions that are called by scripts to perform operations such as reading data from sensors, controlling actuators, and generally working with peripherals. With primitives, you can use the power of scripting to control and monitor hardware components without having to dive into complex hardware-specific code every time you want to change the behavior of a device.
The primary purposes of Primitives in the Uniot include:
Abstraction: Simplifies complex hardware interactions by providing high-level functions that encapsulate low-level operations.
Modularity: Promotes a modular architecture in which hardware functions are packaged into discrete, reusable components.
Flexibility: Provides dynamic and programmable hardware control via scripts, enabling rapid development and iteration.
Maintenance: Simplifies maintenance and upgrades by isolating hardware-specific code in primitives, reducing the impact of changes on the overall system.
Scalability: Supports the addition of new hardware features by registering new primitives, improving system scalability.
Primitives are implemented and managed within the component of the module. The class handles primitive registration, validation, and register management. For more information about registers, see the .
There are two types of primitives:
User-written Primitives: Custom primitives for controlling complex peripherals that require more sophisticated interactions
Default Primitives: Pre-defined primitives for basic digital and analog I/O operations and button interactions
To create a custom primitive, you need to define a primitive function and add it to the Lisp environment. Here's an example that creates a pin_high
primitive to check if a pin is in HIGH state:
Here's an example of setting up registers for common components:
Registers are an abstraction layer that simplifies pin management and hardware access. They act as organized collections of pins grouped by their functionality, making it easier to work with multiple pins and ensuring proper pin configuration.
The register manager provides four register types for default primitives:
dwrite
: Register for writing digital values
Controls digital output pins like LEDs or relays
Accepts boolean values (#t for HIGH, () for LOW)
Pins must be configured using setDigitalOutput()
dread
: Register for reading digital values
Reads from digital input pins like buttons or switches
Returns boolean values (#t for HIGH, () for LOW)
Pins must be configured using setDigitalInput()
awrite
: Register for writing analog values
Controls PWM-capable pins for analog output
Accepts values from 0-1023 for variable control
Commonly used for LED brightness or motor speed
Pins must be configured using setAnalogOutput()
aread
: Register for reading analog values
Reads from analog input pins like sensors
Returns values from 0-1023 representing voltage levels
Used for temperature, light, or other analog sensors
Pins must be configured using setAnalogInput()
Using registers provides several benefits:
Organized pin management and access control
Type safety through proper pin configuration
Simplified hardware abstraction in scripts
Efficient pin state tracking and updates
You can view available primitives and registers for your device on the Uniot Platform. On the Registers page, hovering over a pin value shows its index, which you'll use when writing scripts.
Once registered, this primitive is accessible from both scripts and the .
Default primitives handle basic I/O operations through pin registers. For a complete list of default primitives, see the .
For more information about using primitives in scripts, see the section of the Visual Editor.
: Learn how to use primitives in scripts
: Information on the register system
: List of built-in primitives
: Overview of the Lisp wrapper module
: Detailed documentation on the primitive expeditor