mirror of
https://github.com/BotChain-Robots/firmware.git
synced 2026-07-08 17:47:21 +02:00
Add distance sensor, rewrite OLED to use new i2c library
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(vl53l0x_multiple_sensors)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "multiple_sensors_example.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,180 @@
|
||||
/* VL53L0X Multiple Sensors Example
|
||||
*
|
||||
* This example demonstrates how to use multiple VL53L0X sensors on the same I2C bus
|
||||
* using the new API (vl53l0x_config_with_bus)
|
||||
*
|
||||
* Key points:
|
||||
* - All sensors share the same I2C bus
|
||||
* - Each sensor needs a unique I2C address
|
||||
* - XSHUT pins are used to change addresses at initialization
|
||||
*
|
||||
* Hardware connections:
|
||||
* Sensor 1:
|
||||
* - VL53L0X SCL/SDA -> Shared I2C bus (GPIO 22/21)
|
||||
* - VL53L0X XSHUT -> GPIO 23
|
||||
*
|
||||
* Sensor 2:
|
||||
* - VL53L0X SCL/SDA -> Shared I2C bus (GPIO 22/21)
|
||||
* - VL53L0X XSHUT -> GPIO 25
|
||||
*
|
||||
* Sensor 3:
|
||||
* - VL53L0X SCL/SDA -> Shared I2C bus (GPIO 22/21)
|
||||
* - VL53L0X XSHUT -> GPIO 26
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "vl53l0x.h"
|
||||
|
||||
static const char *TAG = "VL53L0X_MULTI";
|
||||
|
||||
// I2C Configuration
|
||||
#define I2C_MASTER_NUM 0
|
||||
#define I2C_MASTER_SCL_IO 22
|
||||
#define I2C_MASTER_SDA_IO 21
|
||||
|
||||
// Sensor configuration
|
||||
#define NUM_SENSORS 3
|
||||
|
||||
// XSHUT pins for each sensor (must be different)
|
||||
#define SENSOR1_XSHUT 23
|
||||
#define SENSOR2_XSHUT 25
|
||||
#define SENSOR3_XSHUT 26
|
||||
|
||||
// New I2C addresses (must be unique, default is 0x29)
|
||||
#define SENSOR1_ADDR 0x30
|
||||
#define SENSOR2_ADDR 0x31
|
||||
#define SENSOR3_ADDR 0x32
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "VL53L0X Multiple Sensors Example");
|
||||
|
||||
// Step 1: Create a single shared I2C bus
|
||||
i2c_master_bus_config_t bus_config = {
|
||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||
.i2c_port = I2C_MASTER_NUM,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.glitch_ignore_cnt = 7,
|
||||
.flags.enable_internal_pullup = true,
|
||||
};
|
||||
|
||||
i2c_master_bus_handle_t bus_handle;
|
||||
esp_err_t ret = i2c_new_master_bus(&bus_config, &bus_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus: %s", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "I2C bus created successfully");
|
||||
|
||||
// Step 2: Initialize sensors one at a time with unique addresses
|
||||
// We use XSHUT pins to keep sensors in reset while configuring others
|
||||
vl53l0x_t *sensors[NUM_SENSORS];
|
||||
int8_t xshut_pins[NUM_SENSORS] = {SENSOR1_XSHUT, SENSOR2_XSHUT, SENSOR3_XSHUT};
|
||||
uint8_t addresses[NUM_SENSORS] = {SENSOR1_ADDR, SENSOR2_ADDR, SENSOR3_ADDR};
|
||||
|
||||
// First, hold all sensors in reset
|
||||
for (int i = 0; i < NUM_SENSORS; i++) {
|
||||
gpio_reset_pin(xshut_pins[i]);
|
||||
gpio_set_direction(xshut_pins[i], GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(xshut_pins[i], 0); // Keep in reset
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "All sensors held in reset");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
// Initialize each sensor one by one
|
||||
for (int i = 0; i < NUM_SENSORS; i++) {
|
||||
ESP_LOGI(TAG, "\nInitializing sensor %d...", i + 1);
|
||||
|
||||
// Create sensor with shared bus and default address (0x29)
|
||||
sensors[i] = vl53l0x_config_with_bus(
|
||||
bus_handle,
|
||||
xshut_pins[i],
|
||||
0x29, // All start with default address
|
||||
1 // Use 2.8V I/O mode
|
||||
);
|
||||
|
||||
if (!sensors[i]) {
|
||||
ESP_LOGE(TAG, "Failed to configure sensor %d", i + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Release this sensor from reset
|
||||
gpio_set_level(xshut_pins[i], 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); // Wait for sensor to boot
|
||||
|
||||
// Initialize the sensor
|
||||
const char *err = vl53l0x_init(sensors[i]);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "Failed to initialize sensor %d: %s", i + 1, err);
|
||||
vl53l0x_end(sensors[i]);
|
||||
sensors[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Change to unique I2C address
|
||||
vl53l0x_setAddress(sensors[i], addresses[i]);
|
||||
ESP_LOGI(TAG, "Sensor %d initialized with address 0x%02X", i + 1, addresses[i]);
|
||||
|
||||
// Optional: Configure timing budget
|
||||
vl53l0x_setMeasurementTimingBudget(sensors[i], 40000); // 40ms
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "\nAll sensors initialized!\n");
|
||||
|
||||
// Step 3: Start continuous measurements on all sensors
|
||||
for (int i = 0; i < NUM_SENSORS; i++) {
|
||||
if (sensors[i]) {
|
||||
vl53l0x_startContinuous(sensors[i], 100); // 100ms interval
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Read from all sensors in a loop
|
||||
ESP_LOGI(TAG, "Starting continuous measurements from all sensors...");
|
||||
|
||||
for (int iteration = 0; iteration < 30; iteration++) {
|
||||
ESP_LOGI(TAG, "\n--- Measurement %d ---", iteration + 1);
|
||||
|
||||
for (int i = 0; i < NUM_SENSORS; i++) {
|
||||
if (!sensors[i]) {
|
||||
ESP_LOGW(TAG, "Sensor %d: Not available", i + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t range_mm = vl53l0x_readRangeContinuousMillimeters(sensors[i]);
|
||||
|
||||
if (vl53l0x_timeoutOccurred(sensors[i])) {
|
||||
ESP_LOGW(TAG, "Sensor %d: Timeout", i + 1);
|
||||
} else if (vl53l0x_i2cFail(sensors[i])) {
|
||||
ESP_LOGE(TAG, "Sensor %d: I2C error", i + 1);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Sensor %d: %d mm", i + 1, range_mm);
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(150));
|
||||
}
|
||||
|
||||
// Step 5: Stop and cleanup
|
||||
ESP_LOGI(TAG, "\nStopping measurements and cleaning up...");
|
||||
|
||||
for (int i = 0; i < NUM_SENSORS; i++) {
|
||||
if (sensors[i]) {
|
||||
vl53l0x_stopContinuous(sensors[i]);
|
||||
vl53l0x_end(sensors[i]); // Does NOT delete the shared bus
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the shared bus only after all sensors are done
|
||||
i2c_del_master_bus(bus_handle);
|
||||
|
||||
ESP_LOGI(TAG, "Example finished");
|
||||
}
|
||||
6
components/vl53l0x/examples/single_sensor/CMakeLists.txt
Normal file
6
components/vl53l0x/examples/single_sensor/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(vl53l0x_single_sensor)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "single_sensor_example.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,127 @@
|
||||
/* VL53L0X Single Sensor Example
|
||||
*
|
||||
* This example demonstrates basic usage of a single VL53L0X sensor
|
||||
* using the legacy API (vl53l0x_config)
|
||||
*
|
||||
* Hardware connections:
|
||||
* - VL53L0X VCC -> 3.3V or 5V (depending on module)
|
||||
* - VL53L0X GND -> GND
|
||||
* - VL53L0X SCL -> GPIO 22 (or your chosen SCL pin)
|
||||
* - VL53L0X SDA -> GPIO 21 (or your chosen SDA pin)
|
||||
* - VL53L0X XSHUT -> GPIO 23 (optional, for power control)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "vl53l0x.h"
|
||||
|
||||
static const char *TAG = "VL53L0X_SINGLE";
|
||||
|
||||
// I2C Configuration
|
||||
#define I2C_MASTER_NUM 0
|
||||
#define I2C_MASTER_SCL_IO 22
|
||||
#define I2C_MASTER_SDA_IO 21
|
||||
#define VL53L0X_XSHUT_PIN 23 // Set to -1 if not using XSHUT
|
||||
#define VL53L0X_ADDRESS 0x29 // Default I2C address
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "VL53L0X Single Sensor Example");
|
||||
|
||||
// Initialize VL53L0X sensor with legacy API
|
||||
// This creates and manages its own I2C bus
|
||||
vl53l0x_t *sensor = vl53l0x_config(
|
||||
I2C_MASTER_NUM,
|
||||
I2C_MASTER_SCL_IO,
|
||||
I2C_MASTER_SDA_IO,
|
||||
VL53L0X_XSHUT_PIN,
|
||||
VL53L0X_ADDRESS,
|
||||
1 // Use 2.8V I/O mode (set to 0 for 1.8V)
|
||||
);
|
||||
|
||||
if (!sensor) {
|
||||
ESP_LOGE(TAG, "Failed to configure VL53L0X sensor");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "VL53L0X configured successfully");
|
||||
|
||||
// Initialize the sensor
|
||||
const char *err = vl53l0x_init(sensor);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "VL53L0X initialization failed: %s", err);
|
||||
vl53l0x_end(sensor);
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "VL53L0X initialized successfully");
|
||||
|
||||
// Optional: Set timing budget (default is ~33ms)
|
||||
// Higher budget = more accurate but slower
|
||||
err = vl53l0x_setMeasurementTimingBudget(sensor, 50000); // 50ms
|
||||
if (err) {
|
||||
ESP_LOGW(TAG, "Failed to set timing budget: %s", err);
|
||||
}
|
||||
|
||||
// Example 1: Single shot measurements
|
||||
ESP_LOGI(TAG, "\n=== Single Shot Mode ===");
|
||||
for (int i = 0; i < 5; i++) {
|
||||
uint16_t range_mm = vl53l0x_readRangeSingleMillimeters(sensor);
|
||||
|
||||
if (vl53l0x_timeoutOccurred(sensor)) {
|
||||
ESP_LOGW(TAG, "Measurement timeout!");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Range: %d mm", range_mm);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
|
||||
// Example 2: Continuous measurements
|
||||
ESP_LOGI(TAG, "\n=== Continuous Mode ===");
|
||||
ESP_LOGI(TAG, "Starting continuous ranging (200ms interval)...");
|
||||
|
||||
vl53l0x_startContinuous(sensor, 200); // 200ms between measurements
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
uint16_t range_mm = vl53l0x_readRangeContinuousMillimeters(sensor);
|
||||
|
||||
if (vl53l0x_timeoutOccurred(sensor)) {
|
||||
ESP_LOGW(TAG, "Measurement timeout!");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Range: %d mm", range_mm);
|
||||
}
|
||||
|
||||
// Check for I2C errors
|
||||
if (vl53l0x_i2cFail(sensor)) {
|
||||
ESP_LOGE(TAG, "I2C communication error!");
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(250)); // Slightly longer than measurement interval
|
||||
}
|
||||
|
||||
vl53l0x_stopContinuous(sensor);
|
||||
ESP_LOGI(TAG, "Continuous ranging stopped");
|
||||
|
||||
// Example 3: High-speed continuous mode (back-to-back)
|
||||
ESP_LOGI(TAG, "\n=== High-Speed Mode ===");
|
||||
ESP_LOGI(TAG, "Starting back-to-back continuous ranging...");
|
||||
|
||||
vl53l0x_startContinuous(sensor, 0); // 0 = back-to-back mode (fastest)
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
uint16_t range_mm = vl53l0x_readRangeContinuousMillimeters(sensor);
|
||||
ESP_LOGI(TAG, "Range: %d mm", range_mm);
|
||||
vTaskDelay(pdMS_TO_TICKS(50)); // Small delay
|
||||
}
|
||||
|
||||
vl53l0x_stopContinuous(sensor);
|
||||
|
||||
// Cleanup
|
||||
vl53l0x_end(sensor);
|
||||
ESP_LOGI(TAG, "Example finished");
|
||||
}
|
||||
Reference in New Issue
Block a user