suraj0152

VL53L0X.h

Jul 23rd, 2024
512
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.63 KB | Software | 0 0
  1. /**
  2.  * @file VL53L0X.h
  3.  * @author Ryotaro Onuki ([email protected])
  4.  * @brief C Library for VL53L0X as an ESP-IDF component
  5.  * @copyright Copyright (c) 2018 Ryotaro Onuki
  6.  */
  7.  
  8. #ifndef VL53L0X_H
  9. #define VL53L0X_H
  10.  
  11. #include "freertos/FreeRTOS.h"
  12. #include "freertos/semphr.h"
  13. #include "freertos/task.h"
  14.  
  15. #include "driver/gpio.h"
  16. #include "driver/i2c.h"
  17.  
  18. #include "vl53l0x_api.h"
  19. #include "vl53l0x_def.h"
  20. #include "vl53l0x_platform.h"
  21.  
  22. #include "esp_log.h"
  23.  
  24. #define VL53L0X_I2C_ADDRESS_DEFAULT 0x29
  25.  
  26. typedef struct {
  27.     i2c_port_t i2c_port;
  28.     gpio_num_t gpio_xshut;
  29.     gpio_num_t gpio_gpio1;
  30.     VL53L0X_Dev_t vl53l0x_dev;
  31.     SemaphoreHandle_t xSemaphore;
  32.     int32_t TimingBudgetMicroSeconds;
  33. } VL53L0X;
  34.  
  35. bool VL53L0X_Init(VL53L0X *dev);
  36. bool VL53L0X_Reset(VL53L0X *dev);
  37. bool VL53L0X_HardwareReset(VL53L0X *dev);
  38. bool VL53L0X_SoftwareReset(VL53L0X *dev);
  39. bool VL53L0X_SetDeviceAddress(VL53L0X *dev, uint8_t new_address);
  40. bool VL53L0X_Read(VL53L0X *dev, uint16_t *pRangeMilliMeter);
  41. bool VL53L0X_ReadSingleWithPolling(VL53L0X *dev, uint16_t *pRangeMilliMeter);
  42. bool VL53L0X_ReadSingleWithDelay(VL53L0X *dev, uint16_t *pRangeMilliMeter);
  43. bool VL53L0X_ReadSingleWithInterrupt(VL53L0X *dev, uint16_t *pRangeMilliMeter);
  44. void VL53L0X_I2CMasterInit(VL53L0X *dev, gpio_num_t pin_sda, gpio_num_t pin_scl, uint32_t freq);
  45. bool VL53L0X_SetTimingBudget(VL53L0X *dev, uint32_t TimingBudgetMicroSeconds);
  46.  
  47. #endif // VL53L0X_H
  48.  
  49. // Definitions
  50. #include <string.h>
  51. #include "esp_log.h"
  52.  
  53. #define TAG "VL53L0X"
  54.  
  55. static void IRAM_ATTR gpio1_isr(void *arg) {
  56.     VL53L0X *obj = (VL53L0X *)arg;
  57.     xSemaphoreGiveFromISR(obj->xSemaphore, NULL);
  58. }
  59.  
  60. static VL53L0X_Error print_pal_error(VL53L0X_Error status, const char *method) {
  61.     char buf[VL53L0X_MAX_STRING_LENGTH];
  62.     VL53L0X_GetPalErrorString(status, buf);
  63.     ESP_LOGE(TAG, "%s API status: %i : %s\n", method, status, buf);
  64.     return status;
  65. }
  66.  
  67. static VL53L0X_Error init_vl53l0x(VL53L0X_Dev_t *pDevice) {
  68.     VL53L0X_Error status;
  69.     uint8_t isApertureSpads;
  70.     uint8_t PhaseCal;
  71.     uint32_t refSpadCount;
  72.     uint8_t VhvSettings;
  73.  
  74.     status = VL53L0X_DataInit(pDevice);
  75.     if (status != VL53L0X_ERROR_NONE)
  76.         return print_pal_error(status, "VL53L0X_DataInit");
  77.    
  78.     status = VL53L0X_StaticInit(pDevice);
  79.     if (status != VL53L0X_ERROR_NONE)
  80.         return print_pal_error(status, "VL53L0X_StaticInit");
  81.    
  82.     status = VL53L0X_PerformRefSpadManagement(pDevice, &refSpadCount, &isApertureSpads);
  83.     ESP_LOGI(TAG, "refSpadCount = %" PRIu32 ", isApertureSpads = %" PRIu8 "\n", refSpadCount, isApertureSpads);
  84.     if (status != VL53L0X_ERROR_NONE)
  85.         return print_pal_error(status, "VL53L0X_PerformRefSpadManagement");
  86.    
  87.     status = VL53L0X_PerformRefCalibration(pDevice, &VhvSettings, &PhaseCal);
  88.     if (status != VL53L0X_ERROR_NONE)
  89.         return print_pal_error(status, "VL53L0X_PerformRefCalibration");
  90.    
  91.     status = VL53L0X_SetDeviceMode(pDevice, VL53L0X_DEVICEMODE_SINGLE_RANGING);
  92.     if (status != VL53L0X_ERROR_NONE)
  93.         return print_pal_error(status, "VL53L0X_SetDeviceMode");
  94.  
  95.     return status;
  96. }
  97.  
  98. bool VL53L0X_Init(VL53L0X *dev) {
  99.     if (dev->gpio_xshut != GPIO_NUM_MAX) {
  100.         gpio_set_direction(dev->gpio_xshut, GPIO_MODE_OUTPUT);
  101.         gpio_set_level(dev->gpio_xshut, 1);
  102.     }
  103.     if (dev->gpio_gpio1 != GPIO_NUM_MAX) {
  104.         ESP_ERROR_CHECK(gpio_set_direction(dev->gpio_gpio1, GPIO_MODE_INPUT));
  105.         ESP_ERROR_CHECK(gpio_set_pull_mode(dev->gpio_gpio1, GPIO_PULLUP_ONLY));
  106.         ESP_ERROR_CHECK(gpio_pullup_en(dev->gpio_gpio1));
  107.         ESP_ERROR_CHECK(gpio_set_intr_type(dev->gpio_gpio1, GPIO_INTR_POSEDGE));
  108.         ESP_ERROR_CHECK(gpio_install_isr_service(0));
  109.         ESP_ERROR_CHECK(gpio_isr_handler_add(dev->gpio_gpio1, gpio1_isr, dev));
  110.         ESP_ERROR_CHECK(gpio_intr_enable(dev->gpio_gpio1));
  111.     }
  112.  
  113.     dev->vl53l0x_dev.i2c_port_num = dev->i2c_port;
  114.     dev->vl53l0x_dev.i2c_address = VL53L0X_I2C_ADDRESS_DEFAULT;
  115.     VL53L0X_Reset(dev);
  116.  
  117.     if (init_vl53l0x(&dev->vl53l0x_dev) != VL53L0X_ERROR_NONE)
  118.         return false;
  119.    
  120.     if (VL53L0X_ERROR_NONE !=
  121.         VL53L0X_SetGpioConfig(&dev->vl53l0x_dev, 0, VL53L0X_DEVICEMODE_SINGLE_RANGING,
  122.                               VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY,
  123.                               VL53L0X_INTERRUPTPOLARITY_LOW))
  124.         return false;
  125.  
  126.     if (!VL53L0X_SetTimingBudget(dev, 33000))
  127.         return false;
  128.  
  129.     return true;
  130. }
  131.  
  132. bool VL53L0X_Reset(VL53L0X *dev) {
  133.     if (!VL53L0X_SoftwareReset(dev))
  134.         return VL53L0X_HardwareReset(dev);
  135.     return true;
  136. }
  137.  
  138. bool VL53L0X_HardwareReset(VL53L0X *dev) {
  139.     if (dev->gpio_xshut == GPIO_NUM_MAX)
  140.         return false;
  141.  
  142.     gpio_set_level(dev->gpio_xshut, 0);
  143.     vTaskDelay(10 / portTICK_PERIOD_MS);
  144.     gpio_set_level(dev->gpio_xshut, 1);
  145.     vTaskDelay(10 / portTICK_PERIOD_MS);
  146.  
  147.     return true;
  148. }
  149.  
  150. bool VL53L0X_SoftwareReset(VL53L0X *dev) {
  151.     VL53L0X_Error status = VL53L0X_ResetDevice(&dev->vl53l0x_dev);
  152.     if (status != VL53L0X_ERROR_NONE) {
  153.         print_pal_error(status, "VL53L0X_ResetDevice");
  154.         return false;
  155.     }
  156.     return true;
  157. }
  158.  
  159. bool VL53L0X_SetDeviceAddress(VL53L0X *dev, uint8_t new_address) {
  160.     VL53L0X_Error status =
  161.         VL53L0X_SetDeviceAddress(&dev->vl53l0x_dev, new_address << 1);
  162.     if (status != VL53L0X_ERROR_NONE) {
  163.         print_pal_error(status, "VL53L0X_SetDeviceAddress");
  164.         return false;
  165.     }
  166.  
  167.     dev->vl53l0x_dev.i2c_address = new_address;
  168.     return true;
  169. }
  170.  
  171. bool VL53L0X_Read(VL53L0X *dev, uint16_t *pRangeMilliMeter) {
  172.     if (dev->gpio_gpio1 != GPIO_NUM_MAX)
  173.         return VL53L0X_ReadSingleWithInterrupt(dev, pRangeMilliMeter);
  174.     return VL53L0X_ReadSingleWithPolling(dev, pRangeMilliMeter);
  175. }
  176.  
  177. bool VL53L0X_ReadSingleWithPolling(VL53L0X *dev, uint16_t *pRangeMilliMeter) {
  178.     VL53L0X_RangingMeasurementData_t MeasurementData;
  179.     VL53L0X_Error status =
  180.         VL53L0X_PerformSingleRangingMeasurement(&dev->vl53l0x_dev, &MeasurementData);
  181.     if (status != VL53L0X_ERROR_NONE) {
  182.         print_pal_error(status, "VL53L0X_PerformSingleRangingMeasurement");
  183.         return false;
  184.     }
  185.     *pRangeMilliMeter = MeasurementData.RangeMilliMeter;
  186.     if (MeasurementData.RangeStatus != 0)
  187.         return false;
  188.     return true;
  189. }
  190.  
  191. bool VL53L0X_ReadSingleWithDelay(VL53L0X *dev, uint16_t *pRangeMilliMeter) {
  192.     TickType_t xTicksToWait = dev->TimingBudgetMicroSeconds / 1000 / portTICK_PERIOD_MS;
  193.     VL53L0X_Error status;
  194.  
  195.     status = VL53L0X_SetDeviceMode(&dev->vl53l0x_dev, VL53L0X_DEVICEMODE_SINGLE_RANGING);
  196.     if (status != VL53L0X_ERROR_NONE) {
  197.         print_pal_error(status, "VL53L0X_SetDeviceMode");
  198.         return false;
  199.     }
  200.  
  201.     status = VL53L0X_StartMeasurement(&dev->vl53l0x_dev);
  202.     if (status != VL53L0X_ERROR_NONE) {
  203.         print_pal_error(status, "VL53L0X_StartMeasurement");
  204.         return false;
  205.     }
  206.  
  207.     vTaskDelay(xTicksToWait);
  208.  
  209.     VL53L0X_RangingMeasurementData_t MeasurementData;
  210.     status = VL53L0X_GetRangingMeasurementData(&dev->vl53l0x_dev, &MeasurementData);
  211.     if (status != VL53L0X_ERROR_NONE) {
  212.         print_pal_error(status, "VL53L0X_GetRangingMeasurementData");
  213.         return false;
  214.     }
  215.  
  216.     *pRangeMilliMeter = MeasurementData.RangeMilliMeter;
  217.     if (MeasurementData.RangeStatus != 0)
  218.         return false;
  219.  
  220.     VL53L0X_ClearInterruptMask(&dev->vl53l0x_dev, 0);
  221.     if (status != VL53L0X_ERROR_NONE)
  222.         return false;
  223.  
  224.     return true;
  225. }
  226.  
  227. bool VL53L0X_ReadSingleWithInterrupt(VL53L0X *dev, uint16_t *pRangeMilliMeter) {
  228.     if (dev->gpio_gpio1 == GPIO_NUM_MAX)
  229.         return false;
  230.  
  231.     VL53L0X_Error status;
  232.  
  233.     status = VL53L0X_SetDeviceMode(&dev->vl53l0x_dev, VL53L0X_DEVICEMODE_SINGLE_RANGING);
  234.     if (status != VL53L0X_ERROR_NONE) {
  235.         print_pal_error(status, "VL53L0X_SetDeviceMode");
  236.         return false;
  237.     }
  238.  
  239.     xSemaphoreTake(dev->xSemaphore, 0);
  240.  
  241.     status = VL53L0X_StartMeasurement(&dev->vl53l0x_dev);
  242.     if (status != VL53L0X_ERROR_NONE) {
  243.         print_pal_error(status, "VL53L0X_StartMeasurement");
  244.         return false;
  245.     }
  246.  
  247.     xSemaphoreTake(dev->xSemaphore, 1000 / portMAX_DELAY);
  248.  
  249.     VL53L0X_RangingMeasurementData_t MeasurementData;
  250.     status = VL53L0X_GetRangingMeasurementData(&dev->vl53l0x_dev, &MeasurementData);
  251.     if (status != VL53L0X_ERROR_NONE) {
  252.         print_pal_error(status, "VL53L0X_GetRangingMeasurementData");
  253.         return false;
  254.     }
  255.  
  256.     *pRangeMilliMeter = MeasurementData.RangeMilliMeter;
  257.     if (MeasurementData.RangeStatus != 0)
  258.         return false;
  259.  
  260.     VL53L0X_ClearInterruptMask(&dev->vl53l0x_dev, 0);
  261.     if (status != VL53L0X_ERROR_NONE)
  262.         return false;
  263.  
  264.     return true;
  265. }
  266.  
  267. void VL53L0X_I2CMasterInit(VL53L0X *dev, gpio_num_t pin_sda, gpio_num_t pin_scl, uint32_t freq) {
  268.     i2c_config_t conf;
  269.     memset(&conf, 0, sizeof(i2c_config_t));
  270.     conf.mode = I2C_MODE_MASTER;
  271.     conf.sda_io_num = pin_sda;
  272.     conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
  273.     conf.scl_io_num = pin_scl;
  274.     conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
  275.     conf.master.clk_speed = freq;
  276.     ESP_ERROR_CHECK(i2c_param_config(dev->i2c_port, &conf));
  277.     ESP_ERROR_CHECK(i2c_driver_install(dev->i2c_port, conf.mode, 0, 0, 0));
  278. }
  279.  
  280. bool VL53L0X_SetTimingBudget(VL53L0X *dev, uint32_t TimingBudgetMicroSeconds) {
  281.     VL53L0X_Error status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(&dev->vl53l0x_dev, TimingBudgetMicroSeconds);
  282.     if (status != VL53L0X_ERROR_NONE) {
  283.         print_pal_error(status, "VL53L0X_SetMeasurementTimingBudgetMicroSeconds");
  284.         return false;
  285.     }
  286.     dev->TimingBudgetMicroSeconds = TimingBudgetMicroSeconds;
  287.     return true;
  288. }
  289.  
Advertisement
Add Comment
Please, Sign In to add comment