6 ms·
Using a Time-Of-Flight LIDAR Sensor
- quotemstr 10y agoNeat. I'm curious about why the sensor init code looks the way it does though. It's a very long sequence of repetitive register writes. Why not do it like this instead? Table-driven code is underappreciated, I think. static const struct { unsigned address; unsigned value; } inits[] = { { 0x207, 0x01 }, { 0x208, 0x01 }, { 0x096, 0x00 }, ... }; for (size_t i = 0; i < ARRAYSIZE(init_writes); ++i) { uint8_t res = VL_WriteReg8(i2cDeviceAddress, inits[i].address, inits[i].value); if (res != ERR_OK) { VL_OnError(VL_ON_ERROR_INIT_DEVICE); return res; } } return ERR_OK;
- delinka 10y agoIndeed, their init routine seriously violates the DRY principle. At the very least, each section could be implemented by a macro, but I prefer your 'table-driven' implementation.
- Gibbon1 10y agoI have a feeling writing is that way is mostly habit because you often end up with init routines where the device barfs during init for various reasons[1] and you need to execute 'plan b'. That said I'd consider using macro's to be a distant third option. [1] Classic is the uP resets and re-runs the init code on I2C bus peripherals that have already been configured.
- teraflop 10y agoThat change would decrease the repeated code, but I think it would also make the code more brittle. What if the requirements were very slightly different, and you needed to do something different in the middle of the sequence, like writing a register of a different size or sleeping for a millisecond? This situation is crying out for either exception handling, or Go's "errors are values" pattern. (https://blog.golang.org/errors-are-values https://blog.golang.org/errors-are-values)
- MaulingMonkey 10y ago> What if the requirements were very slightly different, and you needed to do something different in the middle of the sequence, like writing a register of a different size or sleeping for a millisecond? Interestingly, I'd argue this is actually a great argument for brittleness in this case. The table oriented code makes it clear to the reader that no such subtle edge cases exist, improving the readability of the code. Although a local macro or better error handling system would also make such things a bit clearer too.
- LeifCarrotson 10y ago> The table oriented code makes it clear to the reader that no such subtle edge cases exist, As an occasional embedded systems programmer, initialization code without subtle edge cases only exists in artificial examples like this one.
- anmorgan 10y agoA friend and myself were talking about this exact same thing the other day (he works in the web / desktop app space and I work in the embedded space). We were working on an embedded project a while back and he didn't like seeing "bit magic" sprinkled throughout the code and I completely agree. I approach this issue in 3 different ways: #define what those series of addresses and values mean, have a function that calls each one semantically, or a function that wraps all of them (what OP is doing). I was going to show an example specific to this, but unfortunately ST did a poor job this time documenting this specific init sequence. If you look at those application notes linked in the tutorial, they just state they are mandatory private registers, which is disheartening. Looking at the example code that ST provides with their Nucleo boards for the evaluation kit of this module, it doesn't shed much more light, except that it seems to be something to do with ranging, tuning, and up-scaling of the data. They have two functions VL6180x_RangeStaticInit() and VL6180x_UpscaleRegInit() that call this sequence, depending on if up-scaling was defined. Software for Nucleo Board for the VL6180X: http://www.st.com/content/st_com/en/products/embedded-software/proximity-sensors-software/stsw-img003.html http://www.st.com/content/st_com/en/products/embedded-softwa... At this point, if I was actually working with this part, I would contact a ST rep and ask them what is up, because it seems weird they are forcing you to write to "private" registers. If you look at the OP's code, you will see that he does wrap this series of code with VL_InitDevice(), and since ST does not have it documented any better than "These settings should be applied in this order with no substitutions", this is what you get. Doing what is suggested, I don't think really gets you much further, imo, but does condense your code, for what it is worth.
- donquichotte 10y agoRange is 10/40/60cm with accuracy 1/2/3mm (apparently there is some kind of scaling factor). I wonder where such short range measurements with such a low accuracy are useful.
- cimnine 10y agoI could imagine this for collision avoidance in a very small UAV, e.g. a vacuuming robot.
- cptskippy 10y agoThe 3m range with ~3mm accuracy is more than enough for large object alignment as well. I've got the VL53L0X being used as a car park sensor in my garage, it's a very complicated version of a tennis ball on a string.
- ThatGeoGuy 10y ago> Range is 10/40/60cm with accuracy 1/2/3mm (apparently there is some kind of scaling factor). The "accuracy" you mention is really what they call "Range Resolution", which is more a measure of precision than accuracy. The range (as well as this resolution) is determined by the modulation frequency of the device, which I presume is the setting you switch to change modes. > I wonder where such short range measurements with such a low accuracy are useful. Another commenter mentioned autonomous vehicles (small vaccum robot), however I think outside of that use case there's really not much. Honestly for most things at that kind of range, I'd probably prefer to use a PMD camera like the Pico Flexx [1][2]. It's a lot more expensive, but you get a much better range, higher frame rate, and takes full images instead of just a single range in front of whatever it is you're building. Granted the range is 0.1-4m because the modulation frequency is fixed, but for most applications where you want autonomous ranging I can't see this being too much of a problem. [1] http://pmdtec.com/picoflexx/downloads/PMD_RD_Brief_CB_pico_flexx_V0201.pdf http://pmdtec.com/picoflexx/downloads/PMD_RD_Brief_CB_pico_f... [2] http://pmdtec.com/picoflexx/ http://pmdtec.com/picoflexx/
- cptskippy 10y agoThe sensors are great for dynamic alignment and calibration. There are plenty of situations where ~3mm accuracy is perfectly fine. In many situations if you can get parts with-in 3mm of one another, mechanical self alignment mechanisms can take you the rest of the way.
- cptskippy 10y agoPololu has published some libraries for both the VL53L0X and VL6180X that make them a lot easier to consume. https://github.com/pololu/vl53l0x-arduino https://github.com/pololu/vl53l0x-arduino https://github.com/pololu/vl6180x-arduino https://github.com/pololu/vl6180x-arduino I've been playing around with the VL53L0X. http://i.imgur.com/KFezaqU.jpg http://i.imgur.com/KFezaqU.jpg http://i.imgur.com/YM5KLRw.jpg http://i.imgur.com/YM5KLRw.jpg
- deutronium 10y agoI used a time of flight sensor in an attempt to measure the specific gravity of beer - https://www.anfractuosity.com/projects/zymeter-simple/ https://www.anfractuosity.com/projects/zymeter-simple/ https://www.sparkfun.com/products/12784 https://www.sparkfun.com/products/12784 - Is the little board I used, and used a logic level converter. I attached a little polystyrene circle to the top of the hydrometer, for the IR to bounce off. Unfortunately the approach didn't work too well because of yeast krausen pushing the hydrometer about.
- pyoung 10y agoThat's neat! Regarding your temp sensor issues, I used the same sensor for beer monitoring. Not sure if is is the same issue, but I was able to resolve it[1]. [1] http://www.blog.pyoung.net/2015/01/28/ds18b20-crc-check-codes/ http://www.blog.pyoung.net/2015/01/28/ds18b20-crc-check-code...
- deutronium 10y agoOoh thanks a lot for the heads up!
- guntars 10y agoIt's crazy, I've totally missed the point at which these things stopped costing thousands of dollars and instead you can get them for $13.95 now.
- Animats 10y agoI know. I went through the hell of trying to build one in the 1990s. I've used the huge SICK LMS line scanner. Now these things are tiny and cheap, at least for short range.
- cr0sh 10y agoI have a couple of the SICK LMS units (picked them up cheap off ebay) - while I like the fact that these tiny and low cost sensors are available (and great for small-scale robotics) - they won't match up to a SICK unit in the near term. There's nothing like the range, 180 deg scanning speed, and general industrial robustness of the SICK LIDARs. Then again, these chips aren't the size of a small coffee maker, and don't weigh a ton, either. I think these devices will occupy a nice niche for when you want something with a better resolution than either the Sharp IR sensors or some ultrasonic pinger - but don't mind the limited range.
- infocollector 10y agoDoes anyone know if this works in sunlight (at noon outside)?
- Animats 10y agoThe data sheet is frustrating. It's not clear whether this device is a carrier-modulated device or a pulse timing device. I think it's carrier-modulated, like most low-end LIDAR devices. Multiple carrier-modulated devices in the same space can interfere. Pulse timing devices, not so much, especially if you randomize the pulse schedule a bit. [1] http://www.st.com/content/ccc/resource/technical/document/datasheet/c4/11/28/86/e6/26/44/b3/DM00112632.pdf/files/DM00112632.pdf/jcr:content/translations/en.DM00112632.pdf http://www.st.com/content/ccc/resource/technical/document/da...