#led-strip #led #esp32-c3 #micro-controller #i2c-sensors #rust

no-std oxide-spark

This crate enables sensor sampling & LED strips control over Wifi/MQTT on ESP Rust Board

4 releases

0.3.3 Sep 12, 2023
0.3.2 Sep 11, 2023
0.3.1 Sep 11, 2023
0.3.0 Sep 8, 2023

#613 in Embedded development

CC-BY-SA-4.0

36KB
815 lines

OxidESPark

OxidESPark is a Rust library for the Rust ESP Board embedding an ESP32-C3 microcontroller (RISC-V). It uses the ESP-IDF framework and provides tools to easily build applications that interact with the physical world.

Its two main goals are:

  • Interfacing various I2C sensors through a simple TOML configuration file
  • Allowing control of various devices

Setup

See the ESP-IDF template for a detailed guide on how to setup a project.

A complete example can be found in the examples folder of this repository.

Configuration file

OxidESPark is configured through a TOML configuration file. A full configuration example can be found in the examples folder of this repository.

Initialization

As no file system is available on a microcontroller, OxidESPark requires a &'static str to embed the configuration file inside the binary. The include_str macro can be used to that end:

use oxide_spark::utils::init::Init;

Init::init(include_str!("OxideSparkConfig.toml"))?;

That init() call also initializes the logging facilities (see the Logging section below).

Logging

The log crate can be used with OxidESPark. Logging facilities are initialized with the library, the only requirement is to set the log_level field in the configuration file:

[esp]
uuid = "esp1"
log_level = "Info"
use log::info;
use oxide_spark::utils::config::CONFIG;

info!("Hello, world!");
info!("Configuration:\n{:#?}", *CONFIG);

warn!("This is a warning!");
error!("This is an error!");

I2c sensors

Any number of sensors can be declared in the configuration file through the optional sensors section:

[[sensors]]
freq = 5
id = "sensor1"
kind = "Shtc3"
metrics = { "Temperature" = "t","Humidity" = "h" }

After that, one must configure the I2C bus and call the init() function to initialize the sensors and start measuring:

use esp_idf_hal::peripherals::Peripherals;
use oxide_spark::{network::i2c::I2c, models::sensor::Metric, sensors::Sensors};

let peripherals = Peripherals::take().unwrap();

let i2c = I2c::init(
   peripherals.i2c0,
   peripherals.pins.gpio8,
   peripherals.pins.gpio10,
).unwrap();

let channel_size = 10;
let (data_sender, data_receiver) = sync_channel::<Metric>(channel_size);

Sensors::init(i2c, &data_sender, None).unwrap();

Supported internal sensors (embedded on the board)

  • SHTC3: temperature and humidity
[[sensors]]
freq = 5
id = "sensor1"
kind = "Shtc3"
metrics = { "Temperature" = "t","Humidity" = "h" }

Coming soon:

Supported external sensors

Each external sensor must be connected to the board's I2C bus (SCL and SDA pins are respectively GPIO 8 and 10).

  • TSL2561: visible and infrared light
[[sensors]]
freq = 3
id = "sensor2"
kind = "Tsl2561"
metrics = { "InfraredLight" = "il", "VisibleInfraredLight" = "vil" }

Coming soon:

  • BME280: temperature, humidity and pressure
  • MPU9250: accelerometer, gyroscope and magnetometer

Supported devices

  • WS2812B: RGB LED strips (including the embedded "1-LED strip" on GPIO 2)
use oxide_spark::models::led_strip::LedStripBuilder;
use oxide_spark_utils::{color::Color::{Chartreuse, Red}, command::led_strip_mode::LedStripMode};

let rgb_led = LedStripBuilder::new()
	.channel(0)
	.gpio(2)
	.length(1)
	.mode(LedStripMode::Full(Red))
	.build()
   .unwrap()
	.init()
   .unwrap();

rgb_led.send(LedStripMode::Full(Chartreuse)).unwrap();

Connectivity

Wifi

Wifi connection is available (though optional) through the configuration file:

[wifi]
auth_method = "WPA2Enterprise"
pwd = "wifi_password"
ssid = "wifi_ssid"
timeout = 8

See AuthMethod for a list of available authentication methods.

use esp_idf_hal::peripherals::Peripherals;
use oxide_spark::network::wifi::Wifi;

let peripherals = Peripherals::take().unwrap();

Wifi::init(peripherals.modem).unwrap();

After the init() call, the Wifi connection is established. If a timeout occurs, the device automatically reboots.

MQTT

MQTT connection is also available (and optional). It requires a Wifi connection to be established first and a broker must of course be running at the given IP and port:

[mqtt]
channel_size = 10
ip = "1.2.3.4"
port = 1883
use oxide_spark::network::mqtt::Mqtt;

let (data_sender, cmd_receiver) = Mqtt::init().unwrap();

data_sender is the sending half of a sync channel used to send data (namely, sensor measures) while cmd_receiver is the receiving half of a sync channel used to receive remote commands.

Dependencies

~7–16MB
~228K SLoC