commit 1184dd9dbd4e41a8f297c217223fafeca97ba978 Author: Alexander Gabriel Date: Tue Jan 20 23:15:59 2026 +0100 init commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/include/README b/include/README new file mode 100644 index 0000000..49819c0 --- /dev/null +++ b/include/README @@ -0,0 +1,37 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the convention is to give header files names that end with `.h'. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..9379397 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into the executable file. + +The source code of each library should be placed in a separate directory +("lib/your_library_name/[Code]"). + +For example, see the structure of the following example libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +Example contents of `src/main.c` using Foo and Bar: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +The PlatformIO Library Dependency Finder will find automatically dependent +libraries by scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..de11d17 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,16 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32doit-devkit-v1] +platform = espressif32 +board = esp32dev +framework = arduino +lib_deps = adafruit/Adafruit_VL53L0X@^1.2.4 +monitor_speed = 115200 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..e9e8ef0 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,197 @@ +#include + +#include +#include + +// Define which Wire objects to use, may depend on platform +// or on your configurations. +#define SENSOR1_WIRE Wire +#define SENSOR2_WIRE Wire +#if defined(WIRE_IMPLEMENT_WIRE1) +#define SENSOR3_WIRE Wire1 +#define SENSOR4_WIRE Wire1 +#define SENSOR5_WIRE Wire1 +#else +#define SENSOR3_WIRE Wire +#define SENSOR4_WIRE Wire +#define SENSOR5_WIRE Wire +#endif +// Setup mode for doing reads +typedef enum { + RUN_MODE_DEFAULT = 1, + RUN_MODE_ASYNC, + RUN_MODE_GPIO, + RUN_MODE_CONT +} runmode_t; + +runmode_t run_mode = RUN_MODE_DEFAULT; +uint8_t show_command_list = 1; + +typedef struct { + Adafruit_VL53L0X *psensor; // pointer to object + TwoWire *pwire; + int id; // id for the sensor + int shutdown_pin; // which pin for shutdown; + int interrupt_pin; // which pin to use for interrupts. + Adafruit_VL53L0X::VL53L0X_Sense_config_t + sensor_config; // options for how to use the sensor + uint16_t range; // range value used in continuous mode stuff. + uint8_t sensor_status; // status from last ranging in continuous. +} sensorList_t; + +// Actual object, could probably include in structure above61 +Adafruit_VL53L0X sensor1; +Adafruit_VL53L0X sensor2; +#ifndef ARDUINO_ARCH_AVR // not enough memory on uno for 4 objects +Adafruit_VL53L0X sensor3; +Adafruit_VL53L0X sensor4; +Adafruit_VL53L0X sensor5; +#endif +// Setup for 4 sensors +sensorList_t sensors[] = { +#ifndef ARDUINO_ARCH_AVR // not enough memory on uno for 4 objects + {&sensor1, &SENSOR1_WIRE, 0x30, 0, 0, Adafruit_VL53L0X::VL53L0X_SENSE_LONG_RANGE, 0, 0}, + {&sensor2, &SENSOR2_WIRE, 0x31, 2, 0, Adafruit_VL53L0X::VL53L0X_SENSE_HIGH_SPEED, 0, 0}, + {&sensor3, &SENSOR3_WIRE, 0x32, 4, 0, Adafruit_VL53L0X::VL53L0X_SENSE_DEFAULT, 0, 0}, + {&sensor4, &SENSOR4_WIRE, 0x33, 5, 0, Adafruit_VL53L0X::VL53L0X_SENSE_DEFAULT, 0, 0}, + {&sensor5, &SENSOR4_WIRE, 0x34, 15, 0, Adafruit_VL53L0X::VL53L0X_SENSE_DEFAULT, 0, 0}, +#else + // AVR sensors move to other pins + {&sensor1, &SENSOR1_WIRE, 0x30, 6, 8, + Adafruit_VL53L0X::VL53L0X_SENSE_LONG_RANGE, 0, 0}, + {&sensor2, &SENSOR2_WIRE, 0x31, 7, 9, + Adafruit_VL53L0X::VL53L0X_SENSE_HIGH_SPEED, 0, 0}, +#endif +}; + +const int COUNT_SENSORS = sizeof(sensors) / sizeof(sensors[0]); + +const uint16_t ALL_SENSORS_PENDING = ((1 << COUNT_SENSORS) - 1); +uint16_t sensors_pending = ALL_SENSORS_PENDING; +uint32_t sensor_last_cycle_time; + +/* + Reset all sensors by setting all of their XSHUT pins low for delay(10), then + set all XSHUT high to bring out of reset + Keep sensor #1 awake by keeping XSHUT pin high + Put all other sensors into shutdown by pulling XSHUT pins low + Initialize sensor #1 with lox.begin(new_i2c_address) Pick any number but + 0x29 and it must be under 0x7F. Going with 0x30 to 0x3F is probably OK. + Keep sensor #1 awake, and now bring sensor #2 out of reset by setting its + XSHUT pin high. + Initialize sensor #2 with lox.begin(new_i2c_address) Pick any number but + 0x29 and whatever you set the first sensor to +*/ +void Initialize_sensors() { + bool found_any_sensors = false; + // Set all shutdown pins low to shutdown sensors + for (int i = 0; i < COUNT_SENSORS; i++) + digitalWrite(sensors[i].shutdown_pin, LOW); + delay(10); + + for (int i = 0; i < COUNT_SENSORS; i++) { + // one by one enable sensors and set their ID + digitalWrite(sensors[i].shutdown_pin, HIGH); + delay(10); // give time to wake up. + if (sensors[i].psensor->begin(sensors[i].id, false, sensors[i].pwire, + sensors[i].sensor_config)) { + found_any_sensors = true; + } else { + Serial.print(i, DEC); + Serial.print(F(": failed to start\n")); + } + } + if (!found_any_sensors) { + Serial.println("No valid sensors found"); + while (1) + ; + } +} +//==================================================================== +// Simple Sync read sensors. +//==================================================================== +void read_sensors() { + // First use simple function + uint16_t ranges_mm[COUNT_SENSORS]; + bool timeouts[COUNT_SENSORS]; + uint32_t stop_times[COUNT_SENSORS]; + + digitalWrite(13, HIGH); + uint32_t start_time = millis(); + for (int i = 0; i < COUNT_SENSORS; i++) { + ranges_mm[i] = sensors[i].psensor->readRange(); + timeouts[i] = sensors[i].psensor->timeoutOccurred(); + stop_times[i] = millis(); + } + uint32_t delta_time = millis() - start_time; + digitalWrite(13, LOW); + + Serial.print(delta_time, DEC); + Serial.print(F(" ")); + for (int i = 0; i < COUNT_SENSORS; i++) { + Serial.print(i, DEC); + Serial.print(F(":")); + Serial.print(ranges_mm[i], DEC); + Serial.print(F(" ")); + Serial.print(stop_times[i] - start_time, DEC); + if (timeouts[i]) + Serial.print(F("(TIMEOUT) ")); + else + Serial.print(F(" ")); + start_time = stop_times[i]; + } + Serial.println(); +} + +//==================================================================== +// Setup +//==================================================================== +void setup() { + Serial.begin(115200); + Wire.begin(); +#if defined(WIRE_IMPLEMENT_WIRE1) + Wire1.begin(); +#endif + // wait until serial port opens ... For 5 seconds max + while (!Serial && millis() < 5000) + ; + + pinMode(13, OUTPUT); + + // initialize all of the pins. + Serial.println(F("VL53LOX_multi start, initialize IO pins")); + for (int i = 0; i < COUNT_SENSORS; i++) { + pinMode(sensors[i].shutdown_pin, OUTPUT); + digitalWrite(sensors[i].shutdown_pin, LOW); + + if (sensors[i].interrupt_pin >= 0) + pinMode(sensors[i].interrupt_pin, INPUT_PULLUP); + } + Serial.println(F("Starting...")); + Initialize_sensors(); +} + +//==================================================================== +// loop +//==================================================================== +void loop() { + if (show_command_list) { + Serial.println( + F("\nSet run mode by entering one of the following letters")); + Serial.println(F(" D - Default mode")); + Serial.println( + F(" A - Asynchronous mode - Try starting all Seonsors at once")); + Serial.println(F(" G - Asynchronous mode - Like above use GPIO pins")); + Serial.println( + F(" C - Continuous mode - Try starting all Seonsors at once")); + show_command_list = 0; + } + switch (run_mode) { + case RUN_MODE_DEFAULT: + read_sensors(); + break; + } + if (run_mode != RUN_MODE_CONT) + delay(250); +} +0 \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html