{"id":20088252,"url":"https://github.com/alexistm/lidarenhanced","last_synced_at":"2025-07-09T03:07:00.028Z","repository":{"id":150829567,"uuid":"46686501","full_name":"AlexisTM/LIDAREnhanced","owner":"AlexisTM","description":"Driver for the LIDARLite v2 and v3 on the Arduino, with many improvements over the base library (Robustness, asynchronous acquisition, higher acquisition frequency, state machine, maintained)","archived":false,"fork":false,"pushed_at":"2023-01-18T08:33:19.000Z","size":465,"stargazers_count":15,"open_issues_count":1,"forks_count":11,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-06T02:39:32.818Z","etag":null,"topics":["arduino","driver","i2c","laser","lasermeter","lidarlite","robust"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlexisTM.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-11-22T23:54:27.000Z","updated_at":"2023-01-18T08:33:24.000Z","dependencies_parsed_at":"2023-04-14T12:53:44.204Z","dependency_job_id":null,"html_url":"https://github.com/AlexisTM/LIDAREnhanced","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/AlexisTM/LIDAREnhanced","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2FLIDAREnhanced","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2FLIDAREnhanced/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2FLIDAREnhanced/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2FLIDAREnhanced/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlexisTM","download_url":"https://codeload.github.com/AlexisTM/LIDAREnhanced/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2FLIDAREnhanced/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264384305,"owners_count":23599609,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","driver","i2c","laser","lasermeter","lidarlite","robust"],"created_at":"2024-11-13T16:12:57.655Z","updated_at":"2025-07-09T03:07:00.021Z","avatar_url":"https://github.com/AlexisTM.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"LIDARLite v3 ENHANCED\n=========================\n\n\u003e Due to the lack of hardware, this goes unmaintained.\n\nIntroduction\n--------------\nThis library tends to improve the **efficiency** and the **robustness** of the poor original acquisition library. It is originally released for the LidarLite v2 (deprecated) and compatible with the LidarLite v3 (release from Garmin) lasermeter. \n\nImprovements over the original library\n--------------------\n- *Asynchronous acquisition*\n- **Non-blocking** architecture\n- *Automatic reset* of the lidars if too much errors\n- *State machine* for each lidar\n- *Maximum speed* readings for many lidars (enable 400kHz I2C)\n- Don't think about lasers anytime, it just make the acquisition in the background.\n\n\n\u003e It is important to note this was developed for a thesis and was not maintained afterwards as I do not have the hardware anymore. Feel free to refactor it, and improve code quality. If you want to maintain the library, I would happily give you ownership.\n\u003e At the time (2016), we needed much faster measurements than the provided library was capable of.\n\nLimitations\n-----------\n- You have to edit the `MAX_LIDARS` in `LidarController.h` to set the number of instances of lidars you will use (default : 8)\n- There is not (yet) velocity reading, it will be implemented with software (to avoid the badly designed blocking architecture) \n- Speed limited by the I2C bandwidth\n\nHow fast is it ?\n-----------\n\nThe maximal speed is mainly limited by I2C speed more than the configuration. Therefore, I advise you to choose the most *stable* than the most speedy. The next step to improve performances is to sync the laser with the expected acquisition time depending on the distance precedently measured. It would allow to improve acquisition and reduce the I2C usage. Also, it could be great to use the constant acquisition.\n\n* On 100 kHz i2c bus\n  - 800Hz With FORCE_RESET_OFFSET **and** ENABLE_STRENGTH_MEASURE to **true**\n  - 1050Hz With FORCE_RESET_OFFSET **or** ENABLE_STRENGTH_MEASURE to **true**\n  - 1300Hz With FORCE_RESET_OFFSET **and** ENABLE_STRENGTH_MEASURE to **false**\n* On 400 kHz i2c bus\n  - 1325Hz With FORCE_RESET_OFFSET **and** ENABLE_STRENGTH_MEASURE to **true**\n  - 1575Hz With FORCE_RESET_OFFSET **or** ENABLE_STRENGTH_MEASURE to **true**\n  - 2080Hz With FORCE_RESET_OFFSET **and** ENABLE_STRENGTH_MEASURE to **false**\n\n\nUsage \n-------\n\n```c++\n#include \"LidarObject.h\"\n#include \"LidarController.h\"\n#include \"I2CFunctions.h\"\n\n#include \u003cWire.h\u003e\n\n#define WIRE400K false\n#define Z1_LASER_TRIG 11\n#define Z1_LASER_EN 12\n#define Z1_LASER_PIN 13\n#define Z1_LASER_AD 0x6E\n\n// 100Hz\n#define DATARATE 100 \n#define DELAY_SEND_MICROS 1000000/DATARATE\n\n\nstatic LidarController Controller;\nstatic LidarObject LZ1;\n\n\n// Delays\nlong now, last;\n\nvoid initLidars() {\n  // Initialisation of the lidars objects\n  LZ1.begin(Z1_LASER_EN, Z1_LASER_PIN, Z1_LASER_AD, 2, 'a');\n  \n  // Initialisation of the controller\n  Controller.begin(WIRE400K);\n  delay(100);\n  Controller.add(\u0026LZ1, 0);\n}\n\nvoid setup() {\n  Serial.begin(57600);\n  while (!Serial); // for compatibility\n  initLidars();\n  last = micros();\n}\n\nvoid loop() {\n  Controller.spinOnce();\n  now = micros();\n  if(now - last \u003e DELAY_SEND_MICROS){\n    last = micros();\n    laserprint();\n  } \n}\n\nvoid laserprint(){\n  Serial.print(\" Measure: \");\n  Serial.print(LZ1.distance);\n  Serial.print(\" Signal strength: \");\n  Serial.println(LZ1.strength);\n  Serial.print(\" Velocity: \");\n  Serial.println(LZ1.velocity);\n}\n```\n\nAPI\n-------\n\nHere is the API basis, you can check the [In-depth API](API_depth.md) to contribute.\n\n### Lidar object\nThe lidar object represents a laser.\n\n#### LidarObject::begin\n\n```C++\nvoid LidarObject.begin(EnablePin, ModePin, I2CAddress, LaserConfiguration, LidarMode, OneCharName);\n\n// used as \nstatic LidarObject LZ1;\nLZ1.begin(12, 13, 0x64, 2, DISTANCE, 'x');\n```\n\n#### LIDAR_STATE enum\n\n```C++\nenum LIDAR_STATE {\n  SHUTING_DOWN = 240,       // Shutdown the laser to reset it\n  NEED_RESET = 48,          // Too much outliers, need to reset\n  RESET_PENDING = 80,       // Wait 15ms after you reset the Lidar, we are waiting in this state\n  NEED_CONFIGURE = 144,     // 15ms passed, we now configure the Lidar\n  ACQUISITION_READY = 32,   // I started an acquisition, need someone to read it\n  ACQUISITION_PENDING = 64, // The acquisition in on progress\n  ACQUISITION_DONE = 128    // I read the data, need to start an acq again\n};\n```\n\n#### LIDAR_MODE enum\n\n```C++\nenum LIDAR_MODE {\n  NONE = 0,                  // Should not be used unless you want to disable a connected laser (could be implemented)\n  DISTANCE = 1,              // Measure distance as fast as possible\n  VELOCITY = 2,              // Measure velocity at a certain rate\n  DISTANCE_AND_VELOCITY = 3  // Measure distance and velocity\n};\n```\n\n#### Data reading\n\n```C++ \n    int distance;      // newest measure\n    int last_distance; // last measure\n    int velocity;       // newest velocity\n    uint8_t strength;   // newest signal strength\n```\n\n#### Callback configuration \n\nCheck the [full example](example/Callback)) !\n\n```C++ \n\n// Define the callback\nvoid distance_callback(LidarObject* self){\n  // self is the laser transmitting the interrupt. \n  Serial.print(self-\u003ename);\n  Serial.print(\":\");\n  Serial.println(self-\u003edistance);\n}\n\n// In the setup, link the callback :\nLZ1.setCallbackDistance(\u0026distance_callback);\nLZ2.setCallbackDistance(\u0026distance_callback);\n```\n\n### LidarController object\n\n#### LidarController::begin\nStart the I2C line with or without fasti2c (400kHz)\n```C++\nvoid begin(bool fasti2c = false);\n```\n\n#### LidarController::add\nAdd a lidar to the controller, if the id is over the maximum number of lidar (8 by default), returns false and do not add the lidar.\n\n```C++\nbool add(LidarObject* _Lidar, uint8_t _id);\n```\n\n#### LidarController::spinOnce\n\nMake a new step in the Lidar State Machine, store results to *int LidarController::distances*\n\nThe functions below are NOT needed if you do not want to use the state machine\n\n```C++\nvoid spinOnce();\n```\n\n#### LidarController::lasers\n\nThe lidars object is an array with the pointers to all the lasers. \n\n```C++\nLidarObjects lidars[MAX_LIDARS];\n\n// Can be used as \nSerial.print(Controller.lidars[0]-\u003edistance);\n```\n\n### Six lasers example\n\n```C++\n#include \"LidarObject.h\"\n#include \"LidarController.h\"\n#include \"I2CFunctions.h\"\n\n#include \u003cWire.h\u003e\n#define WIRE400K false\n/*** Defines : CONFIGURATION ***/\n// Defines Trigger\n#define Z1_LASER_TRIG 11\n#define Z2_LASER_TRIG 8\n#define Z3_LASER_TRIG 5\n#define Z4_LASER_TRIG 2\n#define Z5_LASER_TRIG 16\n#define Z6_LASER_TRIG 19\n// Defines power enable lines of laser\n#define Z1_LASER_EN 12\n#define Z2_LASER_EN 9\n#define Z3_LASER_EN 6\n#define Z4_LASER_EN 3\n#define Z5_LASER_EN 15\n#define Z6_LASER_EN 18\n// Defines laser mode \n#define Z1_LASER_PIN 13\n#define Z2_LASER_PIN 10\n#define Z3_LASER_PIN 7\n#define Z4_LASER_PIN 4\n#define Z5_LASER_PIN 14\n#define Z6_LASER_PIN 17\n//Define address of lasers\n//Those are written during initialisation\n// default address : 0x62\n#define Z1_LASER_AD 0x6E\n#define Z2_LASER_AD 0x66\n#define Z3_LASER_AD 0x68\n#define Z4_LASER_AD 0x6A\n#define Z5_LASER_AD 0x6C\n#define Z6_LASER_AD 0x64\n\n#define NUMBER_OF_LASERS 6\n\n// Maximum datarate\n#define DATARATE 100\n// Actual wait between communications 100Hz = 10ms\n#define DELAY_SEND_MICROS 1000000/DATARATE\n\n// Lidars\nstatic LidarController Controller;\nstatic LidarObject LZ1;\nstatic LidarObject LZ2;\nstatic LidarObject LZ3;\nstatic LidarObject LZ4;\nstatic LidarObject LZ5;\nstatic LidarObject LZ6;\n\n// Delays\nlong now, last;\n\nvoid beginLidars() {\n  // Initialisation of the lidars objects\n  LZ1.begin(Z1_LASER_EN, Z1_LASER_PIN, Z1_LASER_AD, 2, 'x');\n  LZ2.begin(Z2_LASER_EN, Z2_LASER_PIN, Z2_LASER_AD, 2, 'X');\n  LZ3.begin(Z3_LASER_EN, Z3_LASER_PIN, Z3_LASER_AD, 2, 'y');\n  LZ4.begin(Z4_LASER_EN, Z4_LASER_PIN, Z4_LASER_AD, 2, 'Z');\n  LZ5.begin(Z5_LASER_EN, Z5_LASER_PIN, Z5_LASER_AD, 2, 'y');\n  LZ6.begin(Z6_LASER_EN, Z6_LASER_PIN, Z6_LASER_AD, 2, 'Z');\n  \n  // Initialisation of the controller\n  Controller.begin(WIRE400K);\n  delay(100);\n  Controller.add(\u0026LZ1, 0);\n  Controller.add(\u0026LZ2, 1);\n  Controller.add(\u0026LZ3, 2);\n  Controller.add(\u0026LZ4, 3);\n  Controller.add(\u0026LZ5, 4);\n  Controller.add(\u0026LZ6, 5);\n}\n\nvoid setup() {\n  Serial.begin(57600);\n  while (!Serial);\n  beginLidars();\n  last = micros();\n}\n\nvoid loop() {\n  Controller.spinOnce();\n  now = micros();\n  if(now - last \u003e DELAY_SEND_MICROS){\n    last = micros();\n    laserprint();\n  } \n}\n\nvoid laserprint(){\n  for(uint8_t i = 0; i \u003c 6; i++){\n    Serial.print(i);\n    Serial.print(\" - \");\n    Serial.print(Controller.lidars[i]-\u003edistance);\n    Serial.print(\" - \");\n    Serial.println(Controller.lidars[i]-\u003estrength);\n  }\n}\n```\n\n### Explanations\n\n#### Include the libraries and add some defines to use later\n\n```C++\n#include \"LidarObject.h\"\n#include \"LidarController.h\"\n#include \"I2CFunctions.h\"\n\n#include \u003cWire.h\u003e\n#define WIRE400K false\n/*** Defines : CONFIGURATION ***/\n// Defines Trigger\n#define Z1_LASER_TRIG 11\n#define Z2_LASER_TRIG 8\n#define Z3_LASER_TRIG 5\n#define Z4_LASER_TRIG 2\n#define Z5_LASER_TRIG 16\n#define Z6_LASER_TRIG 19\n// Defines power enable lines of laser\n#define Z1_LASER_EN 12\n#define Z2_LASER_EN 9\n#define Z3_LASER_EN 6\n#define Z4_LASER_EN 3\n#define Z5_LASER_EN 15\n#define Z6_LASER_EN 18\n// Defines laser mode \n#define Z1_LASER_PIN 13\n#define Z2_LASER_PIN 10\n#define Z3_LASER_PIN 7\n#define Z4_LASER_PIN 4\n#define Z5_LASER_PIN 14\n#define Z6_LASER_PIN 17\n//Define address of lasers\n//Those are written during initialisation\n// default address : 0x62\n#define Z1_LASER_AD 0x6E\n#define Z2_LASER_AD 0x66\n#define Z3_LASER_AD 0x68\n#define Z4_LASER_AD 0x6A\n#define Z5_LASER_AD 0x6C\n#define Z6_LASER_AD 0x64\n\n#define NUMBER_OF_LASERS 6\n\n// Maximum datarate\n#define DATARATE 100\n// Actual wait between communications 100Hz = 10ms\n#define DELAY_SEND_MICROS 1000000/DATARATE\n\n// Lidars\nstatic LidarController Controller;\nstatic LidarObject LZ1;\nstatic LidarObject LZ2;\nstatic LidarObject LZ3;\nstatic LidarObject LZ4;\nstatic LidarObject LZ5;\nstatic LidarObject LZ6;\n\n// Delays\nlong now, last;\n```\n\n#### Initiation\n\nInitiate Laser objects, begin the I2C and finally add lidars to the controller \n\n```C++\n\n// Initialisation of the lidars objects\n  LZ1.begin(Z1_LASER_EN, Z1_LASER_PIN, Z1_LASER_AD, 2, 'x');\n  LZ2.begin(Z2_LASER_EN, Z2_LASER_PIN, Z2_LASER_AD, 2, 'X');\n  LZ3.begin(Z3_LASER_EN, Z3_LASER_PIN, Z3_LASER_AD, 2, 'y');\n  LZ4.begin(Z4_LASER_EN, Z4_LASER_PIN, Z4_LASER_AD, 2, 'Z');\n  LZ5.begin(Z5_LASER_EN, Z5_LASER_PIN, Z5_LASER_AD, 2, 'y');\n  LZ6.begin(Z6_LASER_EN, Z6_LASER_PIN, Z6_LASER_AD, 2, 'Z');\n  \n  // Initialisation of the controller\n  Controller.begin(WIRE400K);\n  delay(100);\n  Controller.add(\u0026LZ1, 0);\n  Controller.add(\u0026LZ2, 1);\n  Controller.add(\u0026LZ3, 2);\n  Controller.add(\u0026LZ4, 3);\n  Controller.add(\u0026LZ5, 4);\n  Controller.add(\u0026LZ6, 5);\n```\n\n#### Update the state machine\n\nYou just have to use Controller.spinOnce() and it updates the state machine, send/retrieves data to/from lidars.\n\nThen, every DELAY_SEND_MICROS microseconds, get the data\n\n```C++\nvoid loop(){\n  Controller.spinOnce();\n  now = micros();\n  if(now - last \u003e DELAY_SEND_MICROS){\n    last = micros();\n    laserprint();\n} \n```\n\n#### Data extraction\n\n```C++ \nvoid laserprint(){\n  for(uint8_t i = 0; i \u003c 6; i++){\n    Serial.print(i);\n    Serial.print(\" - \");\n    Serial.print(Controller.lidars[i]-\u003edistance);\n    Serial.print(\" - \");\n    Serial.println(Controller.lidars[i]-\u003estrength);\n  }\n}\n```\n\n\nTodo\n--------\n- Velocity readings\n- Independent callbacks for each lasers or when each are done, or one single callback for every lasers\n\nPull requests \n----------\nPull requests are welcome :D\n\nCredits \n------\n* Alexis Paques (alexis[dot]paques[at]gmail[dot]com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexistm%2Flidarenhanced","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexistm%2Flidarenhanced","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexistm%2Flidarenhanced/lists"}