CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I2C troubles.
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

I2C troubles.
PostPosted: Mon Aug 06, 2018 2:36 pm     Reply with quote

Continuing on trying to use the VL53L0X chip to do some distance measuring. I found this product: https://www.robotshop.com/media/files/pdf/tinylidar-tof-range-finder-sensor-datasheet.pdf

it claims to handle the complex API and 'dumb it all down'. Got one, giving it a go. Clock and Data lines look good on the scope, going to ground and up to about 4.3V I only read -1 for the MSB and LSB off the chip. Perhaps someone else can spy what I am missing.

Code:
#USE I2C(MASTER,I2C1, SLOW, FORCE_HW, SMBUS)


Code:
i2c_start();
i2c_write(0x00);                   // reset to 0x10 address
i2c_write(0x06);                   
i2c_stop();

delay_ms(100);

i2c_start();
i2c_write(0x10);
i2c_write(0x4d);                   // set up for single read mode
i2c_write(0x53);                   
i2c_stop();

delay_ms(100);

i2c_start();
i2c_write(0x10);
i2c_write(0x54);                   // disable WDT
i2c_write(0x30);                   
i2c_stop();

delay_ms(100);

while(1) {                        // endless loop

i2c_start();
i2c_write(DISTANCE_ADDRESS);
i2c_write(0x44);                   // single read
msb = i2c_read();
lsb = i2c_read(0);
i2c_stop();

led_toggle();

distance_reading = msb << 8;
distance_reading = distance_reading + lsb;

distance_sum = distance_sum + distance_reading;
distance_index = distance_index + 1;



if(seconds >= 1) {  // one second pasted, average data and send string via BT

 seconds = 0;

if(distance_index > 0) {
 distance_value = (float)((float)(distance_sum)/((float)(distance_index)));
 distance_sum = 0;
 distance_index = 0;
}
else {
 distance_value = distance_reading;
 distance_sum = 0;
 distance_index = 0;
}


fprintf(USB_SERIAL,"**\t%.3f\t#\n\r",distance_value);

fprintf(USB_SERIAL,"**\t%d\t%d\t#\n\r",msb,lsb);
}

}  // end endless while


not the prettiest of code I know. I am using the default address of 0x10 for the device. That is the value of DISTANCE_ADDRESS

MPLAB 8.91
CCS PCM C Compiler, Version 5.064, xxxxx
Windows 10
temtronic



Joined: 01 Jul 2010
Posts: 9205
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Aug 06, 2018 2:52 pm     Reply with quote

OK, I know nothing about that device but...

i2c_write(0x00); // reset to 0x10 address

hmm, is this correct ?

Whenever coding, it helps to add comments to every line ,especially drivers. Costs nothing in codespace, but might help others now or you later, when you ask 'WHY did I do THAT"!??

Also run PCM P's 'I2C scanner' program ,located in the code library. It'll confirm basic, low level access to any I2C device. If it reports 'device found at 0x23' and there's only one device, you now KNOW it's true address.
Some 'camps' use the 7 bit address +R/W while CCS uses 8 bit addresses.

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 06, 2018 3:05 pm     Reply with quote

The tinyLiDAR manual says this:
Quote:

D Read Distance 0x44

Read distance in mm from the most recent measurement
Host -> Sensor
Send Command
0x44 {D}
Sensor -> Host
Read Response
2 bytes with MSB first
Example:
Read from distance from tinyLiDAR at default address of 0x10.
Value read was 0x0690 or 1680mm.
<10:w> 44
<10:r> 06 90

The 'r' and 'w' refers to the i2c r/w bit. If it's a read operation, this bit is
set = 1.

I have edited your main loop code as shown below, so that it works
according to the manual's description. I have indicated the changes
as shown in bold:
Quote:
i2c_start();
i2c_write(0x10);
i2c_write(0x44);
i2c_write(0x11);
msb = i2c_read();
lsb = i2c_read(0);
i2c_stop();


However, I don't actually know for certain whether they are using
7-bit or 8-bit i2c address mode. So follow Temtronic's suggestion about
checking the i2c slave address.


Last edited by PCM programmer on Mon Aug 06, 2018 3:21 pm; edited 1 time in total
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Mon Aug 06, 2018 3:19 pm     Reply with quote

Code:
i2c_start();
i2c_write(0x00);                   // reset to 0x10 address
i2c_write(0x06);                   
i2c_stop();

This probably is wrong, you need to communicate with default address.

And PCM's correction on code is probably right but I think write/read adresses are 0x20 and 0x21 since arduino uses 7 bit adressing while CCS uses 8
_________________
There is nothing you can't do if you try
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Mon Aug 06, 2018 3:34 pm     Reply with quote

Got a device found at 0x20.
I will report more tomorrow.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Mon Aug 06, 2018 3:56 pm     Reply with quote

tried with 0x20 for the base address, and using 0x21 for the read. still -1 reported back. I have commented allot of the code out. Done with it for today.
will try again tomorrow.
temtronic



Joined: 01 Jul 2010
Posts: 9205
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Aug 06, 2018 4:14 pm     Reply with quote

OK, silly question.
What is the value of the I2C pullup resistors ?

Also does PCM P's program work and return with the address ?

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 06, 2018 4:19 pm     Reply with quote

In the link that you gave for documentation, it says:
Quote:
I2C Pull-up resistors: 2x 4.7K SMD

So it has two 4.7K pullups built-in.

When you start working on the project again, post your revised
code, so we can check if you're using the correct slave address
in all sections of the program.
Ttelmah



Joined: 11 Mar 2010
Posts: 19457

View user's profile Send private message

PostPosted: Tue Aug 07, 2018 12:54 am     Reply with quote

0x10, is the Arduino address. 7bit. The PIC address will be 0x20, so this is right.
You are not reversing the I2C bus correctly. You need to issue a read command after a bus restart to reverse the bus...
Personally, simplify. Make a connection between the ground and clear pins for a short while, to reset the chip to factory defaults. This sets it to address 0x20, and the single step mode. Then you can use the basic code from the top of page 6 of the data sheet:
Code:

#define LIDAR 0x20
#define WR 0
#define RD 1

while(1)
{                        // endless loop
   delay_ms(14); //max single read speed 75Hz
   i2c_start();
   i2c_write(LIDAR | WR); //we are writing
   i2c_write('D');  // issue single 'distance read' command
   i2c_start();      //restart
   i2c_write(LIDAR | RD); //select the read address
   msb = i2c_read(); //now read
   lsb = i2c_read(0);
   i2c_stop();

   led_toggle();

   //then your code to deal with this.
}  // end endless while


Note how the I2C bus reversal is done.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Aug 07, 2018 7:34 am     Reply with quote

Still not working. As for pullups I am only using the 4.7K that are on the LIDAR, nothing on my control PCB. I still get -1 for MSB and LSB after doing the suggestions in this thread.

I think my hardware is good because the scanner program reported a device found at 0X20.

Code:
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
/*
*********************************************************************************************
*  DEFINES
*********************************************************************************************
*/

#DEFINE LIDAR 0x20
#DEFINE RD 1
#DEFINE WR 0


Code:
int msb = 0;
int lsb = 0;



Code:
delay_ms(14); //max single read speed 75Hz
   i2c_start();
   i2c_write(LIDAR | WR); //we are writing
   i2c_write('D');  // issue single 'distance read' command
   i2c_start();      //restart
   i2c_write(LIDAR | RD); //select the read address
   msb = i2c_read(); //now read
   lsb = i2c_read(0);
   i2c_stop();


not sure where to go now, I think it is close, but no way to really know.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Aug 07, 2018 7:45 am     Reply with quote

I have simplified the code down to do a simple on board LED turn on/off command 0x47.
This does not work either. Not sure why the scanner program would detect the device, and report the correct base address and simple LED control would not work.
Ttelmah



Joined: 11 Mar 2010
Posts: 19457

View user's profile Send private message

PostPosted: Tue Aug 07, 2018 9:02 am     Reply with quote

Are you sure the internal resistors are enabled?. There are two links on the board that can be cut or made to enable the resistors.
You haven't mentioned what PIC?. On some PIC's the SMBUS option does not work. How did you have the bus setup when you were running the I2C scanner program?. Setting should be the same.
The write should work even if the PIC bus levels were set wrong.
Double check the settings you actually used for the bus scanner program.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Aug 07, 2018 9:19 am     Reply with quote

Yes the internal resistors are enabled. I am configured like the scanner program, that is the USE statement that is in the last post of my code. I am using 16F876 for a PIC, sorry thought I included that with the other specifics.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Aug 07, 2018 12:47 pm     Reply with quote

Just a follow up for the thread. I got the LIDAR to work. A couple of things, one there is a WDT on the board that resets after 3 seconds of no I2C bus activity. I had a really slow loop running to toggle LEDS so, disabled the WDT first thing, then I had to put the chip in single step mode before calling for a measurement. Lastly, Ttelmah's comment about needing to reset the buss is correct, had to put a i2c_stop() in front of it to keep it from hanging after a few reads. After the i2c_stop() was added, correct data flowed and no lock ups.
Isolated it down by focusing on controlling the on board LED first then expanding out. The i2c scanner code was really nice to have to verify that hardware wise, things were good. Thanks everyone. I will post some working code for the group in the next couple days and will post a new thread for this hardware in the CODE section because the datasheet does not do any PIC or CCS code examples. Here is the basic loop that worked:

Code:
delay_ms(14); //max single read speed 75Hz
   i2c_start();
   i2c_write(LIDAR | WR); //we are writing
   i2c_write('D');  // issue single 'distance read' command
   i2c_stop();
   i2c_start();      //restart
   i2c_write(LIDAR | RD); //select the read address
   msb = i2c_read(); //now read
   lsb = i2c_read(0);
   i2c_stop();
Ttelmah



Joined: 11 Mar 2010
Posts: 19457

View user's profile Send private message

PostPosted: Wed Aug 08, 2018 3:23 am     Reply with quote

That is quite interesting.
They don't give any actual bus timing specifications in the data. I've seen the need for a stop/start, rather than a simple restart on a few devices, but they all have delays specified between the last transmitted byte and the start (typically something like 1.5uSec), so:
Code:

   delay_ms(14); //max single read speed 75Hz
   i2c_start();
   i2c_write(LIDAR | WR); //we are writing
   i2c_write('D');  // issue single 'distance read' command
   //i2c_stop();
   delay_us(2); //may also work
   i2c_start();      //restart
   i2c_write(LIDAR | RD); //select the read address
   msb = i2c_read(); //now read
   lsb = i2c_read(0);
   i2c_stop();

May work as well.

On these it is also worth (if doing rapid sequential I2C transfers), adding a 2uSec delay after the I2C stop, since again there are problems if you do a second transaction immediately after the first.

Glad you have it working now. Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group