I have bought VL6180X proximity sensor on breakout (Aliexpress) originally designed for use with arduino. I have tried it use with Raspberry Pi and STM32 (on STM32F429 discovery board). Sensor is in room environment which my mobile phone reports as about 1000 lux. Sensor could be used in ranging mode and ambient light sensor (ALS) mode. In ranging mode it works good in range of 2cm to 18cm (which is OK) but when used in ALS mode it reports all time zero. I modified STM library to report raw value received from sensor before any recalculations to lux and value from the sensor is all time zero or some number near to zero (like 1, 2, or 3). I have tried to modify SYSALS__INTERMEASUREMENT_PERIOD, SYSALS__INTEGRATION_PERIOD and SYSALS__ANALOGUE_GAIN to different values but result from sensor was still very low value (about 10). When i tried to light sensor with xenon light of my phone in original settings value was about 70 (0 lux after recalculation) and after modification of registers it was about 90 (1 lux after recalculation).
Have you any idea what I am doing wrong? Why are the values soo low?
This is my code. There are functions to configure and control UART (could be ignored), then configuration of I2C bus to the sensor (probably could be ignored), function for configure external interrupt on STM (could be ignored) and then main and EXTI3_IRQHandler which handles application logic. There are commented my register improvements and ranging test.
#include "stm32f4xx.h"
#include "vl6180x_api.h"
#include <string.h>
#include <stdlib.h>
void UART_Init() {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
gpio.GPIO_PuPd = GPIO_PuPd_UP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_Init(GPIOC, &gpio);
USART_InitTypeDef uart;
uart.USART_BaudRate = 115200;
uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
uart.USART_Mode = USART_Mode_Tx;
uart.USART_Parity = USART_Parity_No;
uart.USART_StopBits = USART_StopBits_1;
uart.USART_WordLength = USART_WordLength_8b;
USART_Init(USART6, &uart);
USART_Cmd(USART6, ENABLE);
}
void UART_SendByte(char byte) {
while (!USART_GetFlagStatus(USART6, USART_FLAG_TXE))
;
USART_SendData(USART6, byte);
}
void UART_SendString(char* string) {
for (int i = 0; i < strlen(string); i++) {
UART_SendByte(string[i]);
}
}
void VL6180x_I2CInit() {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_OType = GPIO_OType_OD;
gpio.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpio.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2);
GPIO_Init(GPIOB, &gpio);
I2C_InitTypeDef i2c;
i2c.I2C_Mode = I2C_Mode_I2C;
i2c.I2C_Ack = I2C_Ack_Disable;
i2c.I2C_AcknowledgedAddress = 0x00;
i2c.I2C_DutyCycle = I2C_DutyCycle_2;
i2c.I2C_ClockSpeed = 400000;
I2C_Init(I2C2, &i2c);
I2C2->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN | I2C_CR2_ITERREN;
I2C_Cmd(I2C2, ENABLE);
while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)) {
I2C_GenerateSTOP(I2C2, ENABLE);
I2C_SoftwareResetCmd(I2C2, ENABLE);
I2C_SoftwareResetCmd(I2C2, DISABLE);
}
}
int VL6180x_I2CWrite(VL6180xDev_t addr, uint8_t *buff, uint8_t len) {
int status = 0;
I2C_GenerateSTART(I2C2, ENABLE);
while (!I2C_GetITStatus(I2C2, I2C_IT_SB)) {
}
I2C_Send7bitAddress(I2C2, addr << 1, I2C_Direction_Transmitter);
while (!I2C_GetITStatus(I2C2, I2C_IT_ADDR)) {
}
uint32_t sr2 = I2C2->SR2;
int lenInt = len;
while (lenInt--) {
while (!I2C_GetITStatus(I2C2, I2C_IT_TXE)) {
}
I2C_SendData(I2C2, *(buff++));
}
while (!I2C_GetITStatus(I2C2, I2C_IT_BTF)) {
}
I2C_GenerateSTOP(I2C2, ENABLE);
return status;
}
void DISP_ExecLoopBody() {
for (int i = 0; i < 100000; i++) {
}
}
void VL6180x_Failed(char* message) {
while (1) {
}
}
int VL6180x_I2CRead(VL6180xDev_t addr, uint8_t *buff, uint8_t len) {
I2C_GenerateSTART(I2C2, ENABLE);
I2C_ITConfig(I2C2, I2C_IT_SB, ENABLE);
I2C_ITConfig(I2C2, I2C_IT_ADDR, ENABLE);
I2C_ITConfig(I2C2, I2C_IT_RXNE, ENABLE);
I2C_ITConfig(I2C2, I2C_IT_BTF, ENABLE);
while (!I2C_GetITStatus(I2C2, I2C_IT_SB)) {
}
I2C_Send7bitAddress(I2C2, addr << 1, I2C_Direction_Receiver);
while (!I2C_GetITStatus(I2C2, I2C_IT_ADDR)) {
}
uint32_t sr2 = I2C2->SR2;
I2C_AcknowledgeConfig(I2C2, ENABLE);
int intLen = len;
while (intLen--) {
while (!I2C_GetITStatus(I2C2, I2C_IT_RXNE)) {
}
*(buff++) = I2C_ReceiveData(I2C2);
if (intLen == 0) {
I2C_AcknowledgeConfig(I2C2, DISABLE);
}
}
while (!I2C_GetITStatus(I2C2, I2C_IT_RXNE)) {
}
uint32_t dr = I2C2->DR;
I2C_GenerateSTOP(I2C2, ENABLE);
return 0;
}
void EXTI_PC3_init() {
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Mode = GPIO_Mode_IN;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Pin = GPIO_Pin_3;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpio.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &gpio);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource3);
EXTI_InitTypeDef exti;
exti.EXTI_Line = EXTI_Line3;
exti.EXTI_LineCmd = ENABLE;
exti.EXTI_Mode = EXTI_Mode_Interrupt;
exti.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&exti);
NVIC_InitTypeDef nvic;
nvic.NVIC_IRQChannel = EXTI3_IRQn;
nvic.NVIC_IRQChannelCmd = ENABLE;
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&nvic);
}
VL6180xDev_t myDev = 0x29;
int main(void) {
UART_Init();
UART_SendString("OK\r\n");
VL6180x_I2CInit();
for (int i = 0; i < 1000000; i++) {
}
uint8_t devId;
VL6180x_RdByte(myDev, 0x0000, &devId);
uint32_t deviceVer;
VL6180x_RdDWord(myDev, 0x0001, &deviceVer);
uint32_t model_rev_maj = (deviceVer & 0xFF000000) >> 24;
uint32_t model_rev_min = (deviceVer & 0x00FF0000) >> 16;
uint32_t module_rev_maj = (deviceVer & 0x0000FF00) >> 8;
uint32_t module_rev_min = (deviceVer & 0x000000FF) >> 0;
uint32_t id;
VL6180x_RdDWord(myDev, 0x0006, &id);
uint32_t y = (id & 0xF0000000) >> 28;
uint32_t m = (id & 0x0F000000) >> 24;
uint32_t d = (id & 0x00F80000) >> 19;
uint32_t p = (id & 0x00070000) >> 16;
uint32_t s = (id & 0x0000FFF);
VL6180x_InitData(myDev);
//VL6180x_FilterSetState(myDev, 0);
VL6180x_Prepare(myDev);
/*
VL6180x_AlsSetIntegrationPeriod(myDev, 80);
VL6180x_AlsSetInterMeasurementPeriod(myDev, 10);
VL6180x_AlsSetAnalogueGain(myDev, 7);
*/
EXTI_PC3_init();
VL6180x_SetupGPIO1(myDev, GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, INTR_POL_HIGH);
VL6180x_AlsConfigInterrupt(myDev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
VL6180x_ClearAllInterrupt(myDev);
VL6180x_AlsSetSystemMode(myDev, MODE_START_STOP | MODE_CONTINUOUS);
VL6180x_ClearAllInterrupt(myDev);
while (1) {}
/*while (1) {
VL6180x_RangeData_t Range;
VL6180x_RangePollMeasurement(myDev, &Range);
char buff[10];
itoa(Range.range_mm, buff, 10);
int len = strlen(buff);
buff[len] = '\r';
buff[len + 1] = '\n';
buff[len + 2] = '\0';
UART_SendString(buff);
}*/
}
void EXTI3_IRQHandler() {
if (EXTI_GetITStatus(EXTI_Line3)) {
uint16_t Als = 0;
lux_t lux;
VL6180x_RdWord(myDev, RESULT_ALS_VAL, &Als);
VL6180x_AlsGetLux(myDev, &lux);
VL6180x_ClearAllInterrupt(myDev);
EXTI_ClearITPendingBit(EXTI_Line3);
char buff[100];
sprintf(buff, "RAW_ALS: %d\tLUX: %d\r\n", Als, lux);
UART_SendString(buff);
}
}