7 years, 5 months ago.

Converting a VL6180X arduino library to mbed library

Hi, I bought this VL6180X module to use it as a distance sensor with my LPC1768. Unfortunately, no matter what I do I can't get it to work with the libraries provided by MBED. However, it works perfectly fine with an Arduino library on an Arduino. So I was thinking of converting the Arduino library to a MBED library. The VL6180X uses an I2C connection to communicate with the microcontrollers. Since the arduino library is already in C++, I just have to convert the parts of the library that uses arduino functions right?

So this is the part of the arduino library that need converting

include the mbed library with this snippet

#include <VL6180X.h>
#include <Wire.h>

// Defines /////////////////////////////////////////////////////////////////////

// The Arduino two-wire interface uses a 7-bit number for the address,
// and sets the last bit correctly based on reads and writes
#define ADDRESS_DEFAULT 0b0101001

// RANGE_SCALER values for 1x, 2x, 3x scaling - see STSW-IMG003 core/src/vl6180x_api.c (ScalerLookUP[])
static uint16_t const ScalerValues[] = {0, 253, 127, 84};

// Constructors ////////////////////////////////////////////////////////////////

VL6180X::VL6180X(void)
  : address(ADDRESS_DEFAULT)
  , scaling(0)
  , ptp_offset(0)
  , io_timeout(0) // no timeout
  , did_timeout(false)
{
}

void VL6180X::writeReg(uint16_t reg, uint8_t value)
{
  Wire.beginTransmission(address);
  Wire.write((reg >> 8) & 0xff);  // reg high byte
  Wire.write(reg & 0xff);         // reg low byte
  Wire.write(value);
  last_status = Wire.endTransmission();
}

// Writes a 16-bit register
void VL6180X::writeReg16Bit(uint16_t reg, uint16_t value)
{
  Wire.beginTransmission(address);
  Wire.write((reg >> 8) & 0xff);  // reg high byte
  Wire.write(reg & 0xff);         // reg low byte
  Wire.write((value >> 8) & 0xff);  // value high byte
  Wire.write(value & 0xff);         // value low byte
  last_status = Wire.endTransmission();
}

// Writes a 32-bit register
void VL6180X::writeReg32Bit(uint16_t reg, uint32_t value)
{
  Wire.beginTransmission(address);
  Wire.write((reg >> 8) & 0xff);  // reg high byte
  Wire.write(reg & 0xff);         // reg low byte
  Wire.write((value >> 24) & 0xff); // value highest byte
  Wire.write((value >> 16) & 0xff);
  Wire.write((value >> 8) & 0xff);
  Wire.write(value & 0xff);         // value lowest byte
  last_status = Wire.endTransmission();
}

// Reads an 8-bit register
uint8_t VL6180X::readReg(uint16_t reg)
{
  uint8_t value;

  Wire.beginTransmission(address);
  Wire.write((reg >> 8) & 0xff);  // reg high byte
  Wire.write(reg & 0xff);         // reg low byte
  last_status = Wire.endTransmission();

  Wire.requestFrom(address, (uint8_t)1);
  value = Wire.read();
  Wire.endTransmission();

  return value;
}

// Reads a 16-bit register
uint16_t VL6180X::readReg16Bit(uint16_t reg)
{
  uint16_t value;

  Wire.beginTransmission(address);
  Wire.write((reg >> 8) & 0xff);  // reg high byte
  Wire.write(reg & 0xff);         // reg low byte
  last_status = Wire.endTransmission();

  Wire.requestFrom(address, (uint8_t)2);
  value = (uint16_t)Wire.read() << 8; // value high byte
  value |= Wire.read();               // value low byte
  Wire.endTransmission();

  return value;
}

// Reads a 32-bit register
uint32_t VL6180X::readReg32Bit(uint16_t reg)
{
  uint32_t value;

  Wire.beginTransmission(address);
  Wire.write((reg >> 8) & 0xff);  // reg high byte
  Wire.write(reg & 0xff);         // reg low byte
  last_status = Wire.endTransmission();

  Wire.requestFrom(address, (uint8_t)4);
  value = (uint32_t)Wire.read() << 24;  // value highest byte
  value |= (uint32_t)Wire.read() << 16;
  value |= (uint16_t)Wire.read() << 8;
  value |= Wire.read();                 // value lowest byte
  Wire.endTransmission();

  return value;
}

I also need to convert the constrain and millis function from arduino. I have included the full arduino library for reference if it helps. /media/uploads/Khayhen/vl6180x_arduino.cpp /media/uploads/Khayhen/vl6180x_arduino.h It would be real helpful if you could show me how to convert this and how to do the declaration for the I2C communication. Thanks in advanced.

1 Answer

7 years, 4 months ago.

Hi,

Check this out : https://developer.mbed.org/users/highroads/code/VL6180x/ There is already a mbed librairy for your device thingy. And an example there : https://developer.mbed.org/teams/Robotique-FIP/code/VL6180X/

And also, you don't seem familiar with I2C protocol, nor with object oriented programming, try to find a few tutorials online before getting your hands dirty trying to convert librairies. It's no fun going through every single files, looking for everything you'll have to change. Adapting librairies is kind of a tough job, and you're often better starting back from the very beginning. Furthermore, a lot of commonly used boards and modules already have mbed librairies, try the search engine first next time ;)

Also, you don't seem familiar with the I2C protocol, nor with object oriented programming. I'd advise you to look up for some tutorials online if you got time for that. It could really help you understand how those librairies work. And of course, try to study the example codes that you can find online.

Hope that helps.

Sorry for the late reply I had exams for the last month. Yes I'm not very familiar wth the I2C protocol and object oriented programming but I have to finish this for my project which is due very soon so I don have time to learn everything from scratch. Yes I have tried that library and every single library i could fine for this device and no success. In fact the examples don't even compile.

Anyhow, this are my understanding so far about I2C protocol. Please do correct me if I'm wrong. The microcontroller writes and reads data into specific registers which are stated in the datasheet of the sensor. The arduino uses the Wire.h library and the above readReg and writeReg functions to read and write values into the registers respectively. So since these functions use the Wire.h library functions I need to convert them to be able to work with the I2C library of MBED. The rest of the functions in the library only uses the read and write functions so it should not affect the rest. Hope you can help me with this! Thanks

posted by Khayhen Sarveswarah 14 Dec 2016

Quite good understanding of how it works. However, I don't want to give you the answer straight away :) but I'm gonna help a bit. In arduino, the object attached to the I2C communication is in deed "Wire". But it is a unique object : there is only one I2C port on the arduino, so you don't have to specify which pins you'll be using. On mbed, it's different, more like what I2C is in real life : you have to specify the pins used for communication, that have to be compatible with it, and thus your program will be slightly different. But you can find similar functions (actually, they're methods, but whatever) between arduino and mbed. First thing to do is to initialize an I2C object in your software. Check the I2C cookbook on the website (can't find you examples, I'm on my mobile phone right now). Then link that I2C object to your library, aka define it as external in your library, so you can use it there (could be useful to name it "Wire"). Finally, check every occurrence of the "Wire" object and replace every functions that aren't compatible with mbed functions. Then compile and debug, and repeat until it works. I'll try to have a look at this when I get back home.

posted by Pierre David 14 Dec 2016

Ok, so the Arduino way of doing things is even stranger than waht I thought. beginTransmission(address) is used to indicate that an I2C communication is about to take place, then a buffer is filled with all the bytes to transfer, and finally, endTransmission() sends the data. So did I understand the thing.

Anyway, that doesn't change anything. Try this :

- Add "#include "mbed.h" at the beginning of your librairy.h file

- Add "I2C Wire(p28, p27);" in the .h file (change the pin name according to your target board)

- Replace every "beginTransmission(address)" with "write(address << 1)"

- Delete every endTransmission() instructions

That's it for the write operations

- For every read operation, you'll have to replace "requestFrom[...] enTransmission();" with "read(address << 1, (char *)& value, [numberOfBytesToRead]);"

And that should be it.

posted by Pierre David 14 Dec 2016