Template utilities for embedded systems. Built for extremely lightweight applications. Useful for when the STL is too heavy a cost on particular devices. Includes a number of utilities such as:
Simple to use interface for API mode XBee Series 3 modules.
lutil::XBee3 xbee;
lutil::XBee3Adress addr{ 0x01234567,0x01234567 };
xbee.setStream(&Serial2);
uint8_t msg[] = "Send this!"
xbee.send(msg, sizeof(msg));
Full example:
A quick-and-dirty means of printing multiple values without needing so many Serial.println
commands
// Basic
util::Printer::print("Output");
// An otherwise bunch-of-statements.
util::Printer::print("x: % y: % z: %", xval, yval, zval);
An event loop utility class for handling input and custom behaviour. Combined with Processable
subclasses (e.g. Button
) this is an interface to avoid polluting your setup()
and loop()
statement with tons of logic.
namespace util = lutil::v_1;
util::Button<5> my_button; // PIN 5
void pressed_callback() {
Serial.println("The button was pressed!");
}
void setup() {
Serial.begin(115200);
auto &proc = util::Processor::get();
proc.add_processable(&my_button); // Register button
proc.init(); // Initialize elements
// Register a callback when the button get's pressed. The
// button instance will handle debounce filtering and state
// management without clogging the loop()
my_button.when((int)util::ButtonState::Pressed, pressed_callback);
}
void loop() {
util::Processor::get().process(); // Event-style loop
}
You can create your own Processable
classes with callbacks right from the lutil
api.
A state machine defintion class. This helps create a clear understanding of a systems state and runtime. This is a more complex topic so refer to the example.
This is meant to be combined with the Processor
for maximum control over a machine.
A simple vector that will auto size with it's contents.
util::Vec<float> vector;
vector.push(12.0);
vector.push(1.0);
vector.push(4.0);
Serial.println(vector[2]); // 4.0
vector.pop(2); // == 4.0
vector.pop(-1); // == 1.0