VCNL4010

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys,

i have a problem with prohimty/light sensor VCNL4010. I can't read true value from this sensor. 

I adds my code.

Thank's for help.

#include<avr/io.h>
#include<I2C/i2c_master.c>
#include<LCD/lcd44780.c>
#include<util/delay.h>
#include<stdio.h>
void odczyt (void);
	 uint16_t ret;
	 uint16_t ret1;
	 uint16_t result;
int	 flaga=1;
 int main(void){
	 i2c_init();
	 lcd_init();
	 sei();

	 i2c_start(0x26);
	 i2c_write(0x82);
	 i2c_write(0x02);
	 i2c_stop();

	 i2c_start(0x26);
	 i2c_write(0x83);
	 i2c_write(0x0F);
	 i2c_stop();



	 _delay_ms(400);

	 while(1){

odczyt();


lcd_locate(0,0);
lcd_int(ret*256);
lcd_locate(1,0);
lcd_int(ret1);
result= (ret<<8)*256|ret1;
//wynik=wynik*10;
//wynik=wynik/12;
//lcd_int(wynik);
//flaga=0;
		 }


 }

 void odczyt (void){

	 i2c_start(0x26);
	 i2c_write(0x80);
	 i2c_write(0xFF);
	 i2c_stop();


	 i2c_start(0x26);
	 i2c_write(0x87);
	 i2c_stop();
	 i2c_start(0x27);
	ret= (i2c_read_nack()<<8);
	i2c_stop();

	 i2c_start(0x26);
	 i2c_write(0x88);
	 i2c_stop();
	 i2c_start(0x27);
	ret1= i2c_read_nack();
	 _delay_ms(120);
	i2c_stop();



 }

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What were you expecting to happen?

 

What actually happens?

 

What debugging/testing/investigation have you done to account for the difference?

 

What are your findings so far?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did not present the problem exactly. Soryy. 

I testet this proximity  sensor and for 0mm distance in results register 87h and 88h i had 0xFF value. For other distance value in results register was accident.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I continue test and i find error and i read register 80h. I write ti 80h value =0xFF but i read from 80h value=0xe7. What could be the cause?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you read the note at the bottom of page 11 of the datasheet?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, i read and correcred my code but still doesn't work correct. For 0 mm 0x87 = 0xFF and  0x88 = 0xFF. For other distance value are accident.

 

#include<avr/io.h>
#include<I2C/i2c_master.c>
#include<LCD/lcd44780.c>
#include<util/delay.h>
#include<stdio.h>
void odczyt (void);
	 uint8_t ret;
	 uint16_t ret1;
	 uint16_t result;
int	 flaga=1;
 int main(void){
	 i2c_init();
	 lcd_init();
	 sei();


	 i2c_start(0x26);
	 i2c_write(0x82);
	 i2c_write(0x00);
	 i2c_stop();

	 i2c_start(0x26);
	 i2c_write(0x83);
	 i2c_write(0x0F);
	 i2c_stop();


	 i2c_start(0x26);
	 i2c_write(0x80);
	 i2c_write(0x2A);
	 i2c_stop();

	 _delay_ms(400);

	 while(1){

odczyt();


lcd_locate(0,0);
lcd_int(ret);
lcd_locate(1,0);
lcd_int(ret1);
result= (ret<<8)*256|ret1;
		 }

 }

 void odczyt (void){




	 i2c_start(0x26);
	 i2c_write(0x87);
	 i2c_start(0x27);
	 ret= (i2c_read_ack());
	 ret1= i2c_read_nack();
	 _delay_ms(120);
	 i2c_stop();



 }

 

Last Edited: Wed. May 17, 2017 - 12:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kaczbos93 wrote:
value are accident.

Sorry, that's got lost in translation - What do you mean by that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

How do you know your i2c code even works?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For example :

First measurement for 50mm = register value 87h= 0x0d, 88h = 0xe9

Second measurement for 50mm = register value 87h= 0x0a, 88h = 0x37

Only for 0 mm value always is same -  register value 87h= 0ff, 88h = 0xff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman

I think it works because when i write value to registers 80h,82h and i later read it value is correct. Otherwise i read register 81h and read value is 0x21 what does the datasheet agree with.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kaczbos93 wrote:
For example :

First measurement for 50mm = register value 87h= 0x0d, 88h = 0xe9 ...

You need to make clear which question you are replying to!

 

The 'Quote' button is good for that - just quote enough for context.

 

Or state the post number - I guess you're replying to #7 ?

 

So what values would you expect?

 

If you average a number of readings, do they converge on the right value? ie, is it just noise ... ?

 

But Kartman's quesion in #8 is fundamental:

 

How do you know your i2c code even works?

Last Edited: Wed. May 17, 2017 - 12:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I2C is a wonder protocol, in well written functions, they will return a status, but you ignore any value returned by your I2C functions????

How do you know if they are working if you never check, and only assume they must be working. 

 

Jim

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do not know if I understand correctly.

Dou You mean the status returned in my functions in i2c_master.c ?

 

#ifndef  F_CPU
#define F_CPU 16000000UL
#endif

#include <avr/io.h>
#include <util/twi.h>

#include "i2c_master.h"

#define F_SCL 100000UL // SCL frequency
#define Prescaler 1
#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)

void i2c_init(void)
{
	TWBR = (uint8_t)TWBR_val;
}

uint8_t i2c_start(uint8_t address)
{
	// reset TWI control register
	TWCR = 0;
	// transmit START condition 
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
	// wait for end of transmission
	while( !(TWCR & (1<<TWINT)) );
	
	// check if the start condition was successfully transmitted
	if((TWSR & 0xF8) != TW_START){ return 1; }
	
	// load slave address into data register
	TWDR = address;
	// start transmission of address
	TWCR = (1<<TWINT) | (1<<TWEN);
	// wait for end of transmission
	while( !(TWCR & (1<<TWINT)) );
	
	// check if the device has acknowledged the READ / WRITE mode
	uint8_t twst = TW_STATUS & 0xF8;
	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
	
	return 0;
}

uint8_t i2c_write(uint8_t data)
{
	// load data into data register
	TWDR = data;
	// start transmission of data
	TWCR = (1<<TWINT) | (1<<TWEN);
	// wait for end of transmission
	while( !(TWCR & (1<<TWINT)) );
	
	if( (TWSR & 0xF8) != TW_MT_DATA_ACK ){ return 1; }
	
	return 0;
}

uint8_t i2c_read_ack(void)
{
	
	// start TWI module and acknowledge data after reception
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); 
	// wait for end of transmission
	while( !(TWCR & (1<<TWINT)) );
	// return received data from TWDR
	return TWDR;
}

uint8_t i2c_read_nack(void)
{
	
	// start receiving without acknowledging reception
	TWCR = (1<<TWINT) | (1<<TWEN);
	// wait for end of transmission
	while( !(TWCR & (1<<TWINT)) );
	// return received data from TWDR
	return TWDR;
}

uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length)
{
	if (i2c_start(address | I2C_WRITE)) return 1;
	
	for (uint16_t i = 0; i < length; i++)
	{
		if (i2c_write(data[i])) return 1;
	}
	
	i2c_stop();
	
	return 0;
}

uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length)
{
	if (i2c_start(address | I2C_READ)) return 1;
	
	for (uint16_t i = 0; i < (length-1); i++)
	{
		data[i] = i2c_read_ack();
	}
	data[(length-1)] = i2c_read_nack();
	
	i2c_stop();
	
	return 0;
}

uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length)
{
	if (i2c_start(devaddr | 0x00)) return 1;

	i2c_write(regaddr);

	for (uint16_t i = 0; i < length; i++)
	{
		if (i2c_write(data[i])) return 1;
	}

	i2c_stop();

	return 0;
}

uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length)
{
	if (i2c_start(devaddr)) return 1;

	i2c_write(regaddr);

	if (i2c_start(devaddr | 0x01)) return 1;

	for (uint16_t i = 0; i < (length-1); i++)
	{
		data[i] = i2c_read_ack();
	}
	data[(length-1)] = i2c_read_nack();

	i2c_stop();

	return 0;
}

void i2c_stop(void)
{
	// transmit STOP condition
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, notice how most of them return either a status or data.

But you ignore the status in your program, i.e.

 

 i2c_start(0x26);
	 i2c_write(0x87);
	 i2c_start(0x27);
	 ret= (i2c_read_ack());
	 ret1= i2c_read_nack();
	 _delay_ms(120);
	 i2c_stop();

You don't check if an ACK was returned with your start call, how do you know it worked, and if not, how can the rest work?

Same for the i2c_write(), how do you know if that worked?  You don't, you just assumed it did.  So how can you trust the return data from the following read function if the start or write failed?

 

Your code looks like you sat down and started writing it without thought of what you wanted to have happen, you just threw some code at it!

Every program should begin with paper and pen, make a list of what you need, Functions, data, etc.  sketch out a basic flow chart, then refine it.

Once you have a plan for the program, lay out another plan on how you will test each function, what is a good result, what happens if I pass bad data to it, etc.

Now you can begin coding, testing, debugging, rinse and repeat until successful.

 

Examine each step in your code above and decide how you can verify it for correct operation, assume nothing, verify.

Come back if you get stuck, there is LOTS of help here.  

Good luck,

 

Jim