He comprado el sensor de proximidad VL6180X en el arranque ( Aliexpress ) originalmente diseñado para usar con arduino. Lo he probado con Raspberry Pi y STM32 (en el tablero de descubrimiento STM32F429). El sensor está en el ambiente de la habitación, que mi teléfono móvil reporta como 1000 lux. El sensor podría usarse en el modo de rango y en el modo de sensor de luz ambiental (ALS). En el modo de rango, funciona bien en el rango de 2 cm a 18 cm (lo cual está bien), pero cuando se usa en el modo ALS, indica un tiempo cero. Modifiqué la biblioteca STM para informar el valor bruto recibido del sensor antes de cualquier recálculo a lux y el valor del sensor es todo el tiempo cero o algún número cercano a cero (como 1, 2 o 3). Intenté modificar SYSALS__INTERMEASUREMENT_PERIOD, SYSALS__INTEGRATION_PERIOD y SYSALS__ANALOGUE_GAIN a diferentes valores, pero el resultado del sensor aún era muy bajo (alrededor de 10). Cuando intenté encender el sensor con la luz de xenón de mi teléfono, la configuración original tenía un valor de aproximadamente 70 (0 lux después del recálculo) y después de la modificación de los registros, era de aproximadamente 90 (1 lux después del recálculo).
¿Tienes idea de lo que estoy haciendo mal? ¿Por qué los valores son tan bajos?
Este es mi código. Hay funciones para configurar y controlar UART (se podría ignorar), luego la configuración del bus I2C al sensor (probablemente se podría ignorar), la función para configurar una interrupción externa en STM (se podría ignorar) y luego main y EXTI3_IRQHandler que maneja la lógica de la aplicación . Se comentan mis mejoras de registro y prueba de alcance.
#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] = '#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] = '%pre%';
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);
}
}
';
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);
}
}