{"id":4273,"date":"2020-01-22T20:00:15","date_gmt":"2020-01-22T19:00:15","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4273"},"modified":"2025-12-27T17:37:41","modified_gmt":"2025-12-27T16:37:41","slug":"interrupt-driven-handling-of-the-vl53l0x-laser-sensor","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/interrupt-driven-handling-of-the-vl53l0x-laser-sensor\/","title":{"rendered":"Interrupt-driven handling of the VL53L0X laser sensor"},"content":{"rendered":"\n<p>In the last article I described the adventures related to the original API provided for the laser distance sensor <a href=\"https:\/\/sklep.msalamon.pl\/?s=VL53L0X&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=vl053l0x&amp;utm_content=Text\">VL53L0X<\/a>. I got to the point where I managed to run a single measurement. However, I\u2019d like to relieve the microcontroller a bit so it doesn\u2019t have to wait so long for the measurement to finish. The sensor has an interrupt output pin, so why not use it?<\/p>\n\n\n\n<!--more-->\n\n\n\n<p><a href=\"http:\/\/msalamon.pl\/tani-laserowy-pomiar-odleglosci-z-czujnikiem-tof-vl53l0x\/\">You can find the first part with a description of how the sensor works and simple blocking handling here<\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><figure><a href=\"https:\/\/sklep.msalamon.pl\/?s=vl053&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=vl053l0x&amp;utm_content=vl53l0x\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner-1024x341.png\" alt=\"\" width=\"750\" height=\"250\" class=\"aligncenter wp-image-1372 size-large\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner-1024x341.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner-300x100.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner-768x256.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner-24x8.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner-36x12.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner-160x53.png 160w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/VL53L0X-baner.png 1200w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\"><\/a><\/figure><\/h1>\n\n\n\n<h1 class=\"wp-block-heading\">VL53L0X Operating Modes<\/h1>\n\n\n\n<p>Our hero can operate in two modes: single measurement (Single measurement) and continuous measurement (Continuous measurement).<\/p>\n\n\n\n<p>In the first one, we as programmers must make sure to start the measurement, wait for it to finish, and read the result.<\/p>\n\n\n\n<p>In continuous mode, measurements are performed all the time, and our task is only to read the measured values.<\/p>\n\n\n\n<p>Naturally, the idea of using an interrupt comes to mind. We get an interrupt every time the sensor finishes a measurement and has the data ready for us. Interestingly, such an interrupt is generated both in single-measurement mode and in continuous mode. The API probably enables the interrupt in the sensor by default in both cases.<\/p>\n\n\n\n<p>Why an interrupt in single mode? First, so we don\u2019t have to wait for the measurement to finish. Second, using single mode will let us measure distance less often. In continuous mode, the sensor goes as fast as the factory allows.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Test platform<\/h2>\n\n\n\n<p>For testing continuous operation I used the same configuration as in the previous post. If you haven\u2019t seen it yet, I encourage you to read it -&gt;&nbsp;<a href=\"http:\/\/msalamon.pl\/tani-laserowy-pomiar-odleglosci-z-czujnikiem-tof-vl53l0x\/\">Cheap laser distance measurement with the VL53L0X ToF sensor<\/a><\/p>\n\n\n\n<p>In a nutshell, I\u2019m using:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/sklep.msalamon.pl\/produkt\/vl52l0x-laserowy-czujnik-odleglosci-tof\/?utm_source=blog&amp;utm_medium=post&amp;utm_campaign=vl053l0x\">STM32F401CC on a BlackPill board from my store<\/a><\/li>\n\n\n\n<li>STM32CubeIDE v1.1.0<\/li>\n\n\n\n<li>SM32CubeMX v5.4.0 built into the IDE<\/li>\n\n\n\n<li>HAL F4 libraries v1.24.2<\/li>\n\n\n\n<li>The sensor API provided by ST<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Working in continuous mode<\/h2>\n\n\n\n<p>First, it would be good to check how continuous mode works from the examples. Just like before, I\u2019ll take the example from what is provided in the API.&nbsp;<\/p>\n\n\n\n<p>The code looks like this.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  \/\/\n  \/\/ VL53L0X init for Continuous Measurement\n  \/\/\n\n  VL53L0X_WaitDeviceBooted( Dev );\n  VL53L0X_DataInit( Dev );\n  VL53L0X_StaticInit( Dev );\n  VL53L0X_PerformRefCalibration(Dev, &amp;amp;VhvSettings, &amp;amp;PhaseCal);\n  VL53L0X_PerformRefSpadManagement(Dev, &amp;amp;refSpadCount, &amp;amp;isApertureSpads);\n  VL53L0X_SetDeviceMode(Dev, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING);\n\n  VL53L0X_StartMeasurement(Dev);\n  \/* USER CODE END 2 *\/\n\n  \/* Infinite loop *\/\n  \/* USER CODE BEGIN WHILE *\/\n  while (1)\n  {\n\n\t  VL53L0X_Error Status = WaitMeasurementDataReady(Dev);\n\n      if(Status == VL53L0X_ERROR_NONE)\n      {\n          Status = VL53L0X_GetRangingMeasurementData(Dev, &amp;amp;RangingData);\n\n          \/\/ Clear the interrupt\n          VL53L0X_ClearInterruptMask(Dev, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY);\n          VL53L0X_PollingDelay(Dev);\n      } else {\n          break;\n      }\n\n\t  if(RangingData.RangeStatus == 0)\n\t  {\n\t\t  MessageLen = sprintf((char*)Message, \"Measured distance: %i\\n\\r\", RangingData.RangeMilliMeter);\n\t\t  HAL_UART_Transmit(&amp;amp;huart2, Message, MessageLen, 100);\n\t  }\n\n    \/* USER CODE END WHILE *\/\n\n    \/* USER CODE BEGIN 3 *\/\n  }<\/pre>\n\n\n\n<p>After setting continuous mode, it\u2019s enough to start the measurement and the machine is rolling. Unfortunately, the example uses active waiting for the measurement to finish. The API does not provide interrupt-based operation out of the box, so an extra function <em>WaitMeasurementDataReady, <\/em>was added, which actively waits. It\u2019s a pity, because continuous measurement currently looks exactly the same as single measurement, with the only difference being that you don\u2019t have to start the conversion.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"158\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-1024x158.png\" alt=\"\" class=\"wp-image-1380\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-1024x158.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-300x46.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-768x119.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-1536x238.png 1536w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-24x4.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-36x6.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API-160x25.png 160w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_mode_API.png 1680w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>You\u2019ll admit it\u2019s pointless, right? So how do you use an interrupt? Of course, you need to take a few small steps \ud83d\ude42<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using interrupts with the API<\/h2>\n\n\n\n<p>Ok. First, move on to configuring the interrupt in Cube. Set the line where the GPIO1 pin from the sensor is connected as an interrupt input. Yes \u2013 GPIO1 is the interrupt pin on the VL53L0X.<\/p>\n\n\n\n<p>In my project it\u2019s pin PB3, so I enable it as GPIO_EXTI3. Remember to enable this interrupt in the NVIC configuration.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"498\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-1024x498.png\" alt=\"\" class=\"wp-image-1381\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-1024x498.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-300x146.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-768x373.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-1536x747.png 1536w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-24x12.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-36x18.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube-160x78.png 160w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_cube.png 1680w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>And that\u2019s it for configuration. Generate the code.<\/p>\n\n\n\n<p>Now a very important thing. I don\u2019t know why, but the API enables interrupts in the sensor itself right from the start of its operation. This causes a problem in that the first interrupts appear already during initialization. I didn\u2019t dig into whether they actually use this interrupt during initialization. This is what the initialization procedure itself looks like.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"162\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-1024x162.png\" alt=\"\" class=\"wp-image-1382\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-1024x162.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-300x47.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-768x121.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-1536x242.png 1536w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-24x4.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-36x6.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init-160x25.png 160w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_continuous_init.png 1680w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Now, if you have the interrupt enabled in the STM32 before initialization\u2014and you do, because NVIC is always initialized with the interrupt enabled\u2014then there will be a problem. Such a problem that initialization will stop and loop like this.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"155\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-1024x155.png\" alt=\"\" class=\"wp-image-1383\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-1024x155.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-300x46.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-768x117.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-1536x233.png 1536w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-24x4.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-36x5.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init-160x24.png 160w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_error_init.png 1680w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>So you need to DISABLE the interrupt for the duration of initialization. Then everything works nicely \ud83d\ude42<\/p>\n\n\n\n<p>The full initialization will look like this.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  \/\/\n  \/\/ VL53L0X init for Single Measurement\n  \/\/\n\n  HAL_NVIC_DisableIRQ(EXTI3_IRQn);\n\n  VL53L0X_WaitDeviceBooted( Dev );\n  VL53L0X_DataInit( Dev );\n  VL53L0X_StaticInit( Dev );\n  VL53L0X_PerformRefCalibration(Dev, &amp;amp;VhvSettings, &amp;amp;PhaseCal);\n  VL53L0X_PerformRefSpadManagement(Dev, &amp;amp;refSpadCount, &amp;amp;isApertureSpads);\n  VL53L0X_SetDeviceMode(Dev, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING);\n  VL53L0X_StartMeasurement(Dev);\n\n  HAL_NVIC_EnableIRQ(EXTI3_IRQn);<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Interrupt handling<\/h3>\n\n\n\n<p>Alright, but now how do you write the interrupt handler? Look in main at what is executed.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\t  VL53L0X_Error Status = WaitMeasurementDataReady(Dev);\n\n      if(Status == VL53L0X_ERROR_NONE)\n      {\n          Status = VL53L0X_GetRangingMeasurementData(Dev, &amp;amp;RangingData);\n\n          \/\/ Clear the interrupt\n          VL53L0X_ClearInterruptMask(Dev, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY);\n          VL53L0X_PollingDelay(Dev);\n      } else {\n          break;\n      }<\/pre>\n\n\n\n<p>First we wait for data \u2013 the interrupt is supposed to take care of that. Next we fetch the data, clear the interrupt in the sensor, and wait (??? that\u2019s how it was in the example :D).<\/p>\n\n\n\n<p>It\u2019s enough to move the data readout and clearing of the interrupt flag into the interrupt handler and it should work, right? The whole EXTI3 interrupt handler will therefore look like this.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)\n{\n\tif(GPIO_Pin == TOF_INT_Pin)\n\t{\n\t\tVL53L0X_GetRangingMeasurementData(Dev, &amp;amp;RangingData);\n\t\tVL53L0X_ClearInterruptMask(Dev, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY);\n\t\tTofDataRead = 1;\n\t}\n}<\/pre>\n\n\n\n<p>I also added a helper variable so that I don\u2019t print tons of data in main, but only when it has been read.<\/p>\n\n\n\n<p>So you can remove continuous-mode handling from the main loop, because basically it\u2019s now all in the interrupt handler. In the loop you only check whether there was a new sample and print it to the terminal.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  while (1)\n  {\n\n\t  if(TofDataRead == 1)\n\t  {\n\t\tMessageLen = sprintf((char*)Message, \"Measured distance: %i\\n\\r\", RangingData.RangeMilliMeter);\n\t\tHAL_UART_Transmit(&amp;amp;huart2, Message, MessageLen, 100);\n\t\tTofDataRead = 0;\n\t  }\n    \/* USER CODE END WHILE *\/\n\n    \/* USER CODE BEGIN 3 *\/\n  }<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Does it work?<\/h2>\n\n\n\n<p>\u2013 Sir, you sure wrote a lot, but does it work?<br>\u2013 Sir, you bet it does!<\/p>\n\n\n\n<p>Now you just run the code and data will start flying into the terminal. Ok, you\u2019ll say it was the same in single-shot mode. Let\u2019s see what\u2019s happening on the wires.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"157\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-1024x157.png\" alt=\"\" class=\"wp-image-1384\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-1024x157.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-300x46.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-768x118.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-1536x236.png 1536w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-24x4.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-36x6.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts-160x25.png 160w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_between_interrupts.png 1680w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<p>Beautiful! The microcontroller only stirs the I\u00b2C interface when a new sample is ready in the sensor. That\u2019s exactly what we wanted! \ud83d\ude42<\/p>\n\n\n\n<p>The time between interrupts is just under 32 milliseconds. It was similar in single mode.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Interrupt handling<\/h2>\n\n\n\n<p>Let\u2019s also see what the interrupt routine itself looks like and how long it takes.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"157\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-1024x157.png\" alt=\"\" class=\"wp-image-1385\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-1024x157.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-300x46.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-768x117.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-1536x235.png 1536w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-24x4.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-36x6.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine-160x24.png 160w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/01\/vl53l0x_int_interrupt_routine.png 1680w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<p>It takes about 638 \u00b5s at an I\u00b2C clock speed of 400 kHz. Quite a bit of data moves over the bus.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/?utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=vl053l0x&amp;utm_content=nucleo\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"400\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg\" alt=\"\" class=\"wp-image-1593\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg 1200w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-768x256.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>Interrupt-driven handling in continuous mode significantly relieves the microcontroller. However, successive samples still arrive at intervals of about 30 milliseconds. It\u2019s not a speed demon.<\/p>\n\n\n\n<p>Since the last post I\u2019ve been getting tons of questions about this sensor. Most often, questions appear about comparing such a laser sensor with the classic HC-SR04 ultrasonic sensor. <strong>I thought it would be cool to do such a test \ud83d\ude42<\/strong> <strong>If you have any suggestions under what conditions to test both sensors, write in a comment.<\/strong><\/p>\n\n\n\n<p><a href=\"http:\/\/msalamon.pl\/tani-laserowy-pomiar-odleglosci-z-czujnikiem-tof-vl53l0x\/\">You can find the first part with a description of how the sensor works and simple blocking handling here<\/a><\/p>\n\n\n\n<p>As usual, you can find the full project along with the library on my GitHub:<span>&nbsp;<\/span><a href=\"https:\/\/github.com\/lamik\/VL53L0X_API_INT_STM32_HAL\" target=\"_blank\" rel=\"noopener\">link<\/a><\/p>\n\n\n\n<p><span>If you noticed any mistake, disagree with something, would like to add something important, or simply feel like you\u2019d like to discuss this topic, write a comment. Remember that the discussion should be polite and in accordance with the rules of the Polish language.<\/span><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;4273&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;0&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 - (0 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Interrupt-driven handling of the VL53L0X laser sensor&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the last article I described the adventures related to the original API provided for the laser distance sensor VL53L0X. I got to the point where I managed to run a single measurement. However, I\u2019d like to relieve the microcontroller a bit so it doesn\u2019t have to wait so long [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3382,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[175,176,174,177],"class_list":["post-4273","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-electronics","tag-programming","tag-stm32","tag-stm32cubemx"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4273","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/comments?post=4273"}],"version-history":[{"count":3,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4273\/revisions"}],"predecessor-version":[{"id":4381,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4273\/revisions\/4381"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/3382"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4273"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4273"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4273"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}