7 years, 1 month ago.

LPC7168 and CAN communication with Time-of-Flight Sensor

Hello,

I've recently been working on a project to create a suspension sensor using an optical distance sensor. This sensor uses I2C to communicate with our microcontroller and has been consistently printing to a computer with accurate values. However, the next stage is to communicate with the CAN bus. Here is my main code:

#include "mbed.h"
#include <VL6180x.h>

#define VL6180X_ADDRESS 0x29
 
VL6180xIdentification identification;

// mbed uses 8bit addresses shift address by 1 bit left
VL6180x sensor(p28, p27, VL6180X_ADDRESS<<1);
CAN can(p30, p29); //rd, td

void printIdentification(struct VL6180xIdentification *temp){
  printf("Model ID = ");
  printf("%d\n",temp->idModel);
 
  printf("Model Rev = ");
  printf("%d",temp->idModelRevMajor);
  printf(".");
  printf("%d\n",temp->idModelRevMinor);
 
  printf("Module Rev = ");
  printf("%d",temp->idModuleRevMajor);
  printf(".");
  printf("%d\n",temp->idModuleRevMinor);  
 
  printf("Manufacture Date = ");
  printf("%d",((temp->idDate >> 3) & 0x001F));
  printf("/");
  printf("%d",((temp->idDate >> 8) & 0x000F));
  printf("/1");
  printf("%d\n",((temp->idDate >> 12) & 0x000F));
  printf(" Phase: ");
  printf("%d\n",(temp->idDate & 0x0007));
 
  printf("Manufacture Time (s)= ");
  printf("%d\n",(temp->idTime * 2));
  printf("\n\n");
}


int main()
{

    CANMessage messageOut; //formatting CANMessage

    messageOut.format = CANStandard;
    messageOut.id = 0x720; //11100100000 ID in binary
    messageOut.len = 1; //8 bits, 1 byte 

    //the dataToSend which i want is a the data produced by a function in my header 'sensor.getDistance()'
    uint8_t distance; //dataToSend
    messageOut.data[0] = (char)(distance & 0x00ff); //distance is the variable obtained in my header
    messageOut.data[1] = (char)(distance>>8);

    can.frequency(1000000); //arbitrary just now
    can.reset();

    wait_ms(10); // delay .1s

    sensor.getIdentification(&identification); // Retrieve manufacture info from device memory
    printIdentification(&identification); // Helper function to print all the Module information

    if(sensor.VL6180xInit() != 0) {
        printf("FAILED TO INITALIZE\n"); //Initialize device and check for errors
    };

    sensor.VL6180xDefautSettings(); //Load default settings to get started.

    wait_ms(20); // delay

    while(1) {

        //printf("%d\n", sensor.getDistance() );  this is what used to happen; it would print to a computer 

        can.write(messageOut); //hopefully sending data along bus

        wait_ms(10); //100hz

    }
}

So, I believe the message is properly formatted but I don't think I am actually sending the correct data. This is the getDistance() function in the header:

uint8_t VL6180x::getDistance() {
  uint8_t distance;
  VL6180x_setRegister(VL6180X_SYSRANGE_START, 0x01); //Start Single shot mode
  wait_ms(10);
  distance = VL6180x_getRegister(VL6180X_RESULT_RANGE_VAL);
  VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CLEAR, 0x07);
  return distance;
}

Any insight would be great. If you need to see any other bits of the code just ask. Cheers

1 Answer

7 years, 1 month ago.

I suspect it is the evolution of your code for testing that has introduced some issues. These will make it more difficult to help.

    messageOut.len = 1; //8 bits, 1 byte 

the "payload" size of this message is 1-byte, but below it suggests you want to send 2 bytes

    uint8_t distance; //dataToSend
    messageOut.data[0] = (char)(distance & 0x00ff); //distance is the variable obtained in my header
    messageOut.data[1] = (char)(distance>>8);

distance is an 8-bit value, and not initialized, and then split into 2 x 8-bit registers. So, this is quite inconsistent, and not initialized.

uint8_t VL6180x::getDistance() {

getDistance returns only an 8-bit value, so these fragments are not all that consistent with each other.

I'd suggest you revise your while(1) loop, building up the following a step at a time.

  • get the value from the sensor and assign it to a variable.
  • printf that value, and assess if it looks right
  • put that value into the message, and send it.
  • you might also send a fixed value message, something you could easily very as correct, just to prove your CAN communications.

Accepted Answer

Thanks for your reply. I have, as far as i am aware changed the values so they are all 8-bit (sorry if they aren't - I'm a bit new). Here is my modified code:

int main()
{

    CANMessage messageOut; //formatting CANMessage

    messageOut.format = CANStandard;
    messageOut.id = 0x720; //11100100000 ID in binary
    messageOut.len = 1; //8 bits, 1 byte 

    //the dataToSend which i want is a the data produced by a function in my header 'sensor.getDistance()'
    uint8_t distance; //dataToSend
    messageOut.data[0] = (char)(distance >> 8) & 0xff; 

    can.frequency(1000000); //arbitrary just now
    can.reset();

    wait_ms(10); // delay .1s

    sensor.getIdentification(&identification); // Retrieve manufacture info from device memory
    printIdentification(&identification); // Helper function to print all the Module information

    if(sensor.VL6180xInit() != 0) {
        printf("FAILED TO INITALIZE\n"); //Initialize device and check for errors
    };

    sensor.VL6180xDefautSettings(); //Load default settings to get started.

    wait_ms(20); // delay

    while(1) {

        distance = sensor.getDistance();    
        printf("%d\n", distance);

        can.write(messageOut);

        wait_ms(10); //100hz

    }
}

I suspect I may not have initialised uint8_t but I am unsure how exactly you mean. Cheers

posted by Fraser Law 14 Mar 2017

He means that you are trying to use the variable distance before you have set it's value.

int main()
{
 
    CANMessage messageOut; //formatting CANMessage
 
    messageOut.format = CANStandard;
    messageOut.id = 0x720; //11100100000 ID in binary
    messageOut.len = 1; //8 bits, 1 byte 
 
    //the dataToSend which i want is a the data produced by a function in my header 'sensor.getDistance()'
    uint8_t distance; //dataToSend

// You can't set the message data before you read the sensor.
//     messageOut.data[0] = (char)(distance >> 8) & 0xff; 

 
    can.frequency(1000000); //arbitrary just now
    can.reset();
 
    wait_ms(10); // delay .1s
 
    sensor.getIdentification(&identification); // Retrieve manufacture info from device memory
    printIdentification(&identification); // Helper function to print all the Module information
 
    if(sensor.VL6180xInit() != 0) {
        printf("FAILED TO INITALIZE\n"); //Initialize device and check for errors
    };
 
    sensor.VL6180xDefautSettings(); //Load default settings to get started.
 
    wait_ms(20); // delay
 
    while(1) {
 
        distance = sensor.getDistance();    

// changed to %u, distance is unsigned.
        printf("%u\n", distance);
 
// now set the can message data. No need to do anything fancy since everything is 8 bit data.
        messageOut.data[0] = distance; 

        can.write(messageOut);
 
        wait_ms(10); //100hz
 
    }
}
posted by Andy A 14 Mar 2017

I'll give this a bash. Thank you, guys.

EDIT: That's it working, guys, cheers!

EDIT2:This is my final code working as it should.

#include "mbed.h"
#include <VL6180x.h>

#define VL6180X_ADDRESS 0x29
 
VL6180xIdentification identification;

// mbed uses 8bit addresses shift address by 1 bit left
VL6180x sensor(p28, p27, VL6180X_ADDRESS<<1);
CAN can(p30, p29); //rd, td

void printIdentification(struct VL6180xIdentification *temp){
  printf("Model ID = ");
  printf("%d\n",temp->idModel);
 
  printf("Model Rev = ");
  printf("%d",temp->idModelRevMajor);
  printf(".");
  printf("%d\n",temp->idModelRevMinor);
 
  printf("Module Rev = ");
  printf("%d",temp->idModuleRevMajor);
  printf(".");
  printf("%d\n",temp->idModuleRevMinor);  
 
  printf("Manufacture Date = ");
  printf("%d",((temp->idDate >> 3) & 0x001F));
  printf("/");
  printf("%d",((temp->idDate >> 8) & 0x000F));
  printf("/1");
  printf("%d\n",((temp->idDate >> 12) & 0x000F));
  printf(" Phase: ");
  printf("%d\n",(temp->idDate & 0x0007));
 
  printf("Manufacture Time (s)= ");
  printf("%d\n",(temp->idTime * 2));
  printf("\n\n");
}

int main()
{

    CANMessage messageOut; //formatting CANMessage

    messageOut.format = CANStandard;
    messageOut.id = 0x720;
    messageOut.len = 1;

    uint8_t distance; //dataToSend

    can.frequency(100000); 

    wait_ms(10); // delay .1s

    sensor.getIdentification(&identification); // Retrieve manufacture info from device memory
    printIdentification(&identification); // Helper function to print all the Module information

    if(sensor.VL6180xInit() != 0) {
        printf("FAILED TO INITALIZE\n"); //Initialize device and check for errors
    };

    sensor.VL6180xDefautSettings(); //Load default settings to get started.

    wait_ms(20); // delay

    while(1) {


        distance = sensor.getDistance();  
          
        printf("%u\n", distance);  //u for unsigned int
        
        messageOut.data[0] = distance; 
        
        can.write(messageOut);

        wait_ms(10); //100hz
        
        can.reset(); 

    }
}
posted by Fraser Law 14 Mar 2017