Machine weeks
Hero Shot
Here are two examples of drawings made by our machine.
Drawing a face:
Drawing mountains:
Introduction
Launching Session
General Idea
The general idea is to take the concept of the Urumbu machine and improve it in our own way. We want to develop the Urumbu ULB machine, whose main functions are 2D movement (2D axis systems) and a modular tool head. In the first iteration of the project, the 2-axis system will be taken over entirely from the Urumbu 2022 machine, while the modular function of the tool head will be considered. The software side also needs to be thought through, as nothing in particular has been documented on this subject.
If all goes well in terms of planning, a second iteration can be envisaged in which the 2-axis system is redesigned to reduce to the strict minimum the number of unmanufacturable parts to be purchased. Additional tool heads can also be considered.
Tasks Definition & Repartition
There are mainly 2 functions to be developed, each of which can be divided into three themes: mechanical development, electronic development, and software development.
The two functions are the 2-axis system, and the modular tool head.
The distribution of topics was worked out together, with each person taking responsibility for a part of the project. This is described in the table below.
Function | ... Development | Who |
---|---|---|
2D Axis System | Mechanical | Teo & Charlotte |
Electronic | Bogdan & Alex | |
Software | Siméon | |
Modular Tool Head | Mechanical | Luis |
Electronic | Alex | |
Software | Siméon |
Our idea is to start with this distribution, and then eventually redistribute people as tasks progress.
Work Organisation
To organize our work, we decided to use the Trello management tool to see how other team members were progressing. Trello lets you define tasks and the people in charge of them, as well as comment on them. Temporally, you can also define a calendar and assign tasks or progress to it.
Another communication tool is of course the documentation on the FabLab ULB gitlab. Documenting as soon as we can allows others to see the progress we’ve made, and perhaps the difficulties we may encounter.
Finally, we’ve decided to organize a meeting every morning at 10am to discuss the previous day’s progress, the day’s objectives and so on. This scrum meeting system enables us to keep abreast of progress and difficulties, and to offer to help, etc. It’s also a horizontal organization, which we like.
Of course, when it comes to communication, we also have a messaging channel so we can easily communicate with each other.
2D Axis - Mechanical Development
Introduction & Basic Principles
The 2-axis system consists of a frame placed parallel to the work surface. This frame will house a rail that can be moved in the Y direction by means of two modules, referred to here as Y-plates. This will be able to move along the rail to perform movements in the X direction. The combination of the movement of the raille on the frame and the end effector on the rail allows movement in XY (2 dimensions).
Stepper motors will be attached to the frame, and a pulley system will pull the end-effector in the desired direction. The corners of the frame will house the two motors, as well as two pulleys system. The railing will also house a pulley system on either side of it.
The principle of movement is illustrated below. It is a coreXY movement system.
Parts Manufacturing
Our instructor Axel bought aluminium T-slotted framing rails that will be the main components of the machine’s frame. The other mechanical components were either cut using the laser cutter or 3D printed using files available on the UrumbotXY Fall 2022 gitlab. Some files have been modified after some tests, it will be developped below.
Laser cutter
The parts on which the weels and motors are fixed have been cut in plexiglass sheet of 3mm, and then superposed to obtain a resulting thickness of 6mm in order to fit with the screws size.
Before cutting the parts, a characterization of the power/speed of the laser cutter has been made on the plexiglass sheet to know what parameters were the best for a fast and clean cut. Speed: 30% (= 690mm/min), Power: 80%.
3D printing
With the Prusa 3D printer, we printed the pulleys, the adjuster and the spacers for the end effector plate.
The adjusters have a hole slightly shifted from the center in which the screw is inserted. This offset makes it possible to adjust the space between the wheel and the rail, to reduce the gap between the rail and the wheel without causing too much friction.
Purchased Parts
It was necessary to purchase parts such as racks, screws, bolts, wheels and ball bearings. The bill of materials can be consulted here.
Assembly
Assembly here involves making the frame on which the center rail will run. The corners of the frame will house the two motor modules and the two pulley modules. The center rail will house the two Y-Plate modules, as well as the end effector to which the modular tool head system will be attached.
Modules Assembly
Assembly of the different modules that will be fixed on the frame.
1) Y-plates
The Y plates are the modules that will be fixed to the central rail and roll on the frame to create the Y movement. In the picture below, the three wheels that will roll/slide on the frame can be seen in the lower section. Three wheels are necessary to ensure sufficient stability and avoid any unwanted movements. On the top part of the picture, the two pulleys that form the pulley system of this Y-plate can be seen. They are used to bring the threads to the end effector. The yellow part is the asymmetric adjuster used to adjust the tightness of the wheels to the frame rail.
This assembly must be carried out twice, once on each side of the central rail. Washers are used to space the pulleys slightly from the plate. A bolt is added on the wheel side to space the wheel sufficiently from the plate.
2) Motors fixation and pulley
The motor modules house the motors. They are fixed in two corners of the frame. Two special pulleys have been 3D printed to wind the wire and accumulate it in the motor. The pulleys not fixed to the motors are also positioned so as to align the pulleys with the frame. This module also has to be made twice.
3) Corners pulley fixation
Two pulley system modules must be assembled for the two remaining corners of the frame. There is one pulley per row. Two pulley modules need to be made, this time in mirror image to ensure symmetry across the frame. The two pulleys are at different heights to prevent the two rows from touching.
4) End-effector plate
Finally, the end-effector will be mounted on the plate shown below. The tread will also be fixed on this plate. It is composed of 3 wheels, arranged similarly as the ones on the Y-plates.
Frame Assembly
Assembly of the frame includes not only the frame itself, but also the attachment of the various modules to it and the central rail.
Step 1 : U-shaped Frame
We start by mounting three sides of the frame. It’s easier to leave one side empty so that you can slide in the grid that will be made next. We’ll then need to complete the assembly by closing the frame.
Right-angled pieces are used here to bind the railles together. In addition, special inserts are fitted inside the channels, as can be seen in the images below. Two inserts are required per module, and a further 4 inserts are added on the side to assemble the machine stands.
An important detail when fitting the frame rails is to leave a gap between the side bars and the centre bar. This is because the central rail that will slide along the frame must not rub against the frame.
Step 2 : Adding Motor Modules
The two motor modules are added to the frame using suitable inserts and screws. Note that the two modules are in the same direction. This is necessary so that the thread is aligned with the upper pulleys.
Step 3 : Central Rail Assembly
Now it’s time to fit the centre rail. Using 4 inserts, we attach the two Y plate modules. The rail can then be slid over the two frame rails left open.
Step 4 : Closing the Frame
Now that the centre rail is inserted into the frame, the frame can be closed using the fourth bar of the frame. Once again, two right-angled pieces are used, taking care to leave a gap between this upper central bar and the two side bars. There are also 4 inserts on the side to fix the stands of the machine, as on the other side.
Step 5 : Adding Pulley Modules & Stands
We can now fix the pulley system modules to the top of the frame using four inserts. The machine stands can also be added.
Step 6 : Adding End Effector
The end effector plate is fixed on the central frame by removing one wheel to slide the two other on the rail and putting back the third wheel.
When the first part is fixed on the frame, the rest of the end-effector plate can be assembled, in particular the part on which the thread will bed fixed.
Step 7 : Adding Thread System
There are 2 threads to fix: they both start from the end-effector plate and end there as well. The thread first goes in the pulley of the y-plate, then goes in the two 2 motor pulleys, by starting by the bottom.
Then the thread is wrapped around the pulleys, before going to the corner pulley.
Final Result : Structure With Threads
Testing
We did a first test before attaching the end-effector plate with the thread, to be sure that there was not too much friction between the wheels and the rails.
After adding the thread we tested the structure again.
On the video below, we can see that when the end-effector is doing a diagonal, only one of the 2 motors is turning. The, when the end-effector is going vertically, the 2 motors are rotating.
2D Axis Improvements
Improvement Thread Crossing
In the initial version of the structure, the threads cross at one point, causing friction between them with each movement of the motors. To prevent the threads from breaking due to the friction between them, we added an extra pulley, as shown in the picture below. To do so, we just modified the dxf file of an existing plate to attach the pulley on it.
Z Axis - Mechanical Development
As an improvement of the machine, we decided to add a third axis to the structure. To keep the modular idea of the machine, the Z axis can be added as an option, by mounting an additional structure on the existing 2D structure of the machine. In this case, the end effector is thus attached to the Z axis to allow his movement, and the working bed is fixed in the 2D structure instead of the end effector. The only limiting factor is the working area that is reduced in the XY plane, but it can be solved by doing a bigger structure in the first place.
The designed is based on the solution explored in the urumbu project, aand can be found here. Some changes have been made in the Z-axis, and will be developped below.
Parts Manufacturing
Laser cutter
We cut the same parts as before for the end-effector module, and for the motor. We also changed the design of the motor plate design and adapted it too fix 2 pulleys on it.
3D printing
We printed 3 bearing pulleys and one more to be attached to the motor, one plate for the wire attachment, one adjuster and 3 spacers.
Purchased Parts
We used the remaining parts of the first kit that we bought.
Assembly
As mentioned above, the idea is to add an additional structure without changing the basic 2-axis structure. The first step is to assemble the frame, which will be attached to the base structure, and then the Z-axis, which will be attached to the frame.
Frame Assembly
Step 1 : Adding Side Structures
We start by assembling the structure using the extruded rails we’ve purchased. Given that they’re 50 cm long, we decided to cut some of them in 2 to get our structure 25 cm above the 2-axis frame. We start by making two sides as shown below on either side of the base frame.
Step 2 : Adding Middle Rail
The center rail is then added in a fairly basic way. This rail will be fixed, so the position will have to be adapted according to the tool to be used later.
Axis Assembly
Step 1 : Fixing the motor and pulleys on the Z axis
The motor is attached on one side of the Z axis, with one bearing pulley and one motor pulley. On the other side, 2 pulleys are attached.
Step 2 : Fixing the end-effector module on the Z-axis
The same end-effector module as the one for the 2D axis have been assembled and then fixed on the Z axis.
Step 3 : Adding the thread system
Now that the various modules are attached to our Z axis, we need to add the thread that will move the end-effector.
Step 3 : Adding the Z axis on the structure
Last step is to attach the Z axis on the structure ! The final result is shown below.
Final Result : 3D Structure
The fixed Z axis allows vertical movement of a tool. The XY axes are used to move the work plane that holds the raw material.
Testing
Below, a short video showing the movement of the two end-effectors: the one on the Z axis, and the one on the XY plane.
2D Axis - Electronic Development
The Motors!
To carry out the movement of the axes, the type of motor could have been selected, but step motors are the ones selected par excellence for CNC developments, due to their ease of use, their good precision and their widespread applications on the web. Stepper motors use a cogged wheel and electromagnets to rotate the wheel one ‘step’ at a time.
Each HIGH pulse sent energizes the coil, attracting the teeth closest to the cogged wheel and driving the motor one step forward.
Photo by lastminuteengineers
Our system, unlike other CNC developments based on the very popular Ramps shields, aims to be completely modular, so each Axis will have its own microcontroller with its corresponding independent USB output. Therefore, we believe that it will be much easier to incorporate new modules and continue their development in the near future.
To use and control which motor, a power interface is necessary, an electronic device that translates the logic values produced by the microcontroller into high voltage and current values necessary to drive the motor. In the market there are simpler and more complex solutions depending on the demands of the project, in our case we choose the Driver par excellence for this type of projects.
For single-stepper-motor applications, a driver like the L298N is fine, but if you want to construct your own CNC machine or 3D printer, you’ll need a dedicated stepper motor driver like the A4988. Due to the simplicity of the step motor control and the variety of stepping modes provided by the A4988 driver, it is an ideal solution for building applications that require precise and reliable stepper motor control, such as the movement control of beds, heads, and assemblies in various CNC plotting, milling, and 3D printer designs. The fact that it only requires two pins to control the speed and direction of the bipolar stepper motors like the NEMA is pretty neat, too.
With nothing more to define, create a small PCB for each motor, to do this use the Kicad PCB design software, already worked on in previous weeks and which has turned out to be very useful.
To test the PCB, use the following code fragment without libraries to check its operation, what it does is turn it for 2 seconds to one side and then 2 seconds to the other…“easy and for the all family.”
const int dirPin = 25;
const int stepPin = 26;
const int stepsPerRevolution = 200;
void setup()
{
// Declare pins as Outputs
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
// Set motor direction clockwise
digitalWrite(dirPin, HIGH);
// Spin motor slowly
for(int x = 0; x < stepsPerRevolution; x++)
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(2000);
digitalWrite(stepPin, LOW);
delayMicroseconds(2000);
}
delay(1000); // Wait a second
// Set motor direction counterclockwise
digitalWrite(dirPin, LOW);
// Spin motor quickly
for(int x = 0; x < stepsPerRevolution; x++)
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000);
}
delay(1000); // Wait a second
}
2D Axis - Software Development
In this segment, our goal is to develop a numerical controller that, based on a specific file input, will generate motion control. Given that we’re working with a pen plotter scenario, the input will typically be an SVG file.
We have two alternatives for this task:
- Transform the SVG into G-code and utilize an intermediate motion controller, such as an Arduino Mega equipped with GRBL.
- Employ our laptop as the motion controller, allowing us to write the code in a higher-level language like Python.
We opt for the second approach, which aligns with Urumbu’s philosophy of a “controllerless” design that virtualizes low-level controls in high-level parallel software. The Urumbu codebase already includes a motion controller capable of parsing G-code from XY files. However, we aim to enhance this functionality to directly support SVG files. This is because converting to G-code is not only unnecessary but also results in loss of information. Indeed, the benefit of gcode is to create a intermediate representation of the path to be interpreted by the motion controller but as we get rid of the motion controller we don’t need that intermediate representation. Finally, the current SVG parser in the Urumbu code only supports linear move commands (G0, G1).
However, we cannot directly extract control signal for the stepper motors from the SVG.
From SVG to polylines
The SVG file format uses mathematical primitives to represent shapes. These primitives include lines, curves (cubic and quadratic Bézier), arcs, and more complex shapes like polygons and paths. Each of these primitives is defined by a set of parameters. For example, a line is defined by two points (start and end), a cubic Bézier curve is defined by four points (start, end, and two control points), and so on.
To convert these primitives into a path that a machine can follow, we need to discretize them into a series of small, straight line segments (Polylines). This process is called tessellation. For example, a Bézier curve can be tessellated into a series of straight lines by repeatedly subdividing it at the midpoint.
Fortunately, there’s an excellent Python software that can handle this task: Axidraw. Axidraw is an open-source initiative that offers both software and hardware solutions for pen plotters.
Axidraw is available as an extension for Inkscape, as well as a Python API. Here’s how you can install it
python -m pip install https://cdn.evilmadscientist.com/dl/ad/public/AxiDraw_API.zip
The primary challenge we encountered was that Axidraw requires a connection to the motor board via serial for most of its functions, and it won’t proceed without this connection. Initially, we considered modifying the hardware connection layer of Axidraw to fit the Urumbu architecture. However, due to time constraints and the fact that our plotter’s electronic components were only completed a day before the deadline, this wasn’t feasible.
We worked our way around that by using the estimate_time.py example script that does not need serial connection and we work our way up to find the few lines of code that enable to convert a svg input to a set of polyline path.
The final script is pretty short :
from pyaxidraw import axidraw
ad = axidraw.AxiDraw() # Create class instance
ad.plot_setup(filename) # Parse the input file
ad.options.preview = True
ad.plot_run()
layers = ad.digest.layers
for layer in ad.digest.layers:
for path in layer.paths:
for subpath in path.subpaths:
#do job
The layers are the different layer of the original svg. Then, the pathes are a set of polylines that you can traverse without raising the pen. Finally, the subpath are all the linear segment that form that polyline. In the above example, the layer is the ensemble of both the rectangle and the triangle, each shape is a different path, and each edge in a subpath.
Here we can see how a super small circle is converted to polyline by axidrax :
In the following section we will have a look at how we can use that hierarchy to create motion control.
From polylines to motion control
In this section, we conceptualize a motion control command as a step, direction order at a specific time, t. This concept aligns with our final decision to use the Pololu stepper driver on our motor board. The ‘step’ can be either true, indicating that the motor takes a step, or false, signifying that the motor remains idle. The ‘direction’ can be either forward or backward. If we apply this to both motors, it implies that at each control step, the end effector can execute one of the movements illustrated below:
Conventional motion controllers like Axidraw’s or GRBL’s generate trajectories with smooth acceleration and deceleration profiles to minimize vibrations and maximize speed (ramping up and down speed). However, to simplify our task, we’ve chosen to adhere to the simpler constant velocity control approach utilized in the original Urumbu code.
The code snippet below illustrates the primary steps involved in the plotting process. Initially, the SVG file is parsed using the parse_svg
function as previously described. For each continuous polyline (subpath), the servo is initially lifted, moved to the first coordinates, and then lowered. Subsequently, a line action is added to the queue for each subsequent point on the polyline. This process is repeated for each subpath. Once the parsing is complete, the action queue is filled and we transition to the module manager.
The module manager instantiates the various motors and servos and initiates the main loop for consuming actions. When a LineAction is encountered, it sets the starting position of the line to the start position defined in the LineAction. It then calculates the target position along the line.
The tick_motor
function is responsible for advancing the motor forward or backward if the x or y distance exceeds half a step distance. The m.steps
value represents the current step index of the motor (for instance, if the motor has taken 200 steps forward and 100 steps backward since the start of the plot, the index is 100). By computing the integer rounding of pos_motors[j] * m.steps_per_unit
, we determine the nearest step index we should be at to be as close as possible to the actual position on the line at time t. If this value matches the current step index, we don’t tick; if it’s larger, we tick forward; if it’s smaller, we tick backward.
If a servo action is encontered, the servo is lowered or lift accordingly.
def parse_svg(filename, action_queue, default_feedrate, servo_up_action=None, servo_down_action=None):
# ...
for layer in ad.digest.layers:
for path in layer.paths:
for subpath in path.subpaths:
for i, (x, y) in enumerate(path):
if i == 0:
action_queue.put(servo_up_action)
action_queue.put(Line([x, y], feedrate))
action_queue.put(servo_down_action)
else:
action_queue.put(Line([x, y], feedrate))
class Stepper(Module):
# ...
def step(self, forward):
self.steps += 1 if forward else -1
if self.reverse:
forward = not forward
if not self.preview:
self.write(b"f" if forward else b"r")
# ...
class Line(PathAction):
def __init__(self, pos_end, feedrate):
self.pos_start = np.zeros_like(pos_end)
self.pos_end = np.array(pos_end)
self.duration = -1
self.feedrate = feedrate
def init(self, pos_start):
self.pos_start = np.array(pos_start)
mask_nan = np.isnan(self.pos_end)
self.pos_end[mask_nan] = self.pos_start[mask_nan]
self.duration = np.linalg.norm(self.pos_end - self.pos_start) / self.feedrate
def __call__(self, t):
if t > self.duration:
# end move
return None
u = t / self.duration
return self.pos_start * (1 - u) + self.pos_end * u
def modules_manager(action_queue, modules_config, pos_transformer=None, preview=False):
# ..
n_axis = len(modules_axis)
pos = np.zeros((n_axis,))
pos_motors = np.zeros((n_axis,))
def tick_motor():
if pos_transformer is None:
pos_motors[:] = pos[:]
else:
pos_transformer(pos, pos_motors)
for j in range(n_axis):
m = modules_axis[j] #m is a Stepper object
s = int(pos_motors[j] * m.steps_per_unit)
if m.steps < s:
m.step(True)
elif m.steps > s:
m.step(False)
# ...
while True:
if not action_queue.empty():
# ...
for sub_action in action:
if isinstance(sub_action, PathAction):
# time in s, ~us resolution
sub_action.init(pos)
while True:
t = time.perf_counter()
# path is a time function
pos_new = sub_action(t - t0)
if pos_new is None:
# done
break
tick_motor()
elif isinstance(sub_action, ServoAction):
#Move servo up or down
Preview functionnality
We added a preview functionality to the code :
Firmware
This will depends on the motor driver
Stepper
#define DIR 26
#define STEP 27
#define MS1 0
#define MS2 7
#define MS3 6
void setup() {
Serial.begin(0);
digitalWrite(STEP,LOW);
pinMode(STEP,OUTPUT);
digitalWrite(DIR,LOW);
pinMode(DIR,OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
// 1/16 step
pinMode(MS1, OUTPUT);
digitalWrite(MS1, HIGH);
pinMode(MS2, OUTPUT);
digitalWrite(MS2, HIGH);
pinMode(MS3, OUTPUT);
digitalWrite(MS3, HIGH);
}
void loop() {
if (Serial.available()) {
char c = Serial.read();
if (c == 'f') {
digitalWrite(DIR,HIGH);
digitalWrite(STEP,HIGH);
delayMicroseconds(2);
digitalWrite(STEP,LOW);
}
else if (c == 'r') {
digitalWrite(DIR,LOW);
digitalWrite(STEP,HIGH);
delayMicroseconds(2);
digitalWrite(STEP,LOW);
}
}
}
Servo
void setup() {
Serial.begin(0);
digitalWrite(SERVO,LOW);
pinMode(SERVO,OUTPUT);
}
void loop() {
uint16_t duration;
if (Serial.available()) {
Serial.readBytes((char *)&duration,2);
if (duration == 65535L) {
// special command, reply with button value
int btn = digitalRead(BUTTON);
Serial.write(btn ? '1' : '0');
}
else {
digitalWrite(SERVO,HIGH);
delayMicroseconds(duration);
digitalWrite(SERVO,LOW);
}
}
}
The impact of microstepping
Possible enhancements
- Fork and adapt the axidraw inkscape extension : This would allow to have a better controller and benefit from hatch fill functionality.
- Permanetly rename tty port so that we don’t have to plug the motor and servo in a defined order. Indeed for now, motor 1 is configured to be on tty0, motor two on tty1 and servo on tty2. And port are assigned in order.
Modular Tool Head - Mechanical Development
The goal of this section is to design and make an effector that will hold a drawing instrument in place. A ballpoint pen will be used for testing purposes, but any other instrument can be used as a replacement. This effector can accommodate a servomotor in addition to the drawing instrument, enabling it to move vertically (referred to as the Z-axis hereafter), as well as the PCB. The PCB was specifically designed and manufactured in our laboratory for this purpose.
The design of the effector
The effector was designed based on one of the variants of the 4xiDraw drawing machine, which can be found in the following Thingiverse link.
Below are the shown parts used:
Only two designs were modified. The first modification was made to the motor base, to which a new base was added to mate with the base of the previous Urumbu effector. The second modification was made to the Z-axis motion system to accommodate the designed plate. Both modifications can be seen in the figure below.
The final design and assemble is show below:
Modular Tool Head - Electronic Development
Servos are motors that allow you to precisely control physical movement because they generally move to a position rather than continuously rotating. Servos contain a small DC motor connected to the output shaft through gears. The output shaft drives a servo horn and is also linked to a potentiometer (pot). Due to this simplicity, the servos can be controlled without the need for drivers, just with a PWM PIN.
Photo by lastminuteengineers
In addition to the movement in this module, we wanted to include the possibility of self-leveling for when the head was changed, to correct small unevenness in the work table or for future developments, finally, after evaluating different options we opted for the VL6180 sensor.
Once again for the design of the PCB we will use Kicad (which the truth is that you have already taken a liking to it)
Finally, to check the sensor, I used the native Arduino library but I did not get good results, so I used an example from a third-party library called SparkFun_ToF_Range_Finder-VL6180_Arduino_Library-master.
/******************************************************************************
* SparkFun_VL6180X_demo.ino
* Example Sketch for VL6180x time of flight range finder.
* Casey Kuhns @ SparkFun Electronics
* 10/29/2014
* https://github.com/sparkfun/SparkFun_ToF_Range_Finder-VL6180_Arduino_Library
*
* The VL6180x by ST micro is a time of flight range finder that
* uses pulsed IR light to determine distances from object at close
* range. The average range of a sensor is between 0-200mm
*
* Resources:
* This library uses the Arduino Wire.h to complete I2C transactions.
*
* Development environment specifics:
* IDE: Arduino 1.0.5
* Hardware Platform: Arduino Pro 3.3V/8MHz
* VL6180x Breakout Version: 1.0
* **Updated for Arduino 1.6.4 5/2015**
*
* This code is beerware. If you see me (or any other SparkFun employee) at the
* local pub, and you've found our code helpful, please buy us a round!
*
* Distributed as-is; no warranty is given.
******************************************************************************/
#include <Wire.h>
#include <SparkFun_VL6180X.h>
/*const float GAIN_1 = 1.01; // Actual ALS Gain of 1.01
const float GAIN_1_25 = 1.28; // Actual ALS Gain of 1.28
const float GAIN_1_67 = 1.72; // Actual ALS Gain of 1.72
const float GAIN_2_5 = 2.6; // Actual ALS Gain of 2.60
const float GAIN_5 = 5.21; // Actual ALS Gain of 5.21
const float GAIN_10 = 10.32; // Actual ALS Gain of 10.32
const float GAIN_20 = 20; // Actual ALS Gain of 20
const float GAIN_40 = 40; // Actual ALS Gain of 40
*/
#define VL6180X_ADDRESS 0x29
VL6180xIdentification identification;
VL6180x sensor(VL6180X_ADDRESS);
void setup()
{
Serial.begin(115200); // Start Serial at 115200bps
Wire.begin(); // Start I2C library
delay(100); // 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)
{
Serial.println("Failed to initialize. Freezing..."); // Initialize device and check for errors
while (1)
;
}
sensor.VL6180xDefautSettings(); // Load default settings to get started.
delay(1000); // delay 1s
}
void loop()
{
// Get Ambient Light level and report in LUX
Serial.print("Ambient Light Level (Lux) = ");
// Input GAIN for light levels,
// GAIN_20 // Actual ALS Gain of 20
// GAIN_10 // Actual ALS Gain of 10.32
// GAIN_5 // Actual ALS Gain of 5.21
// GAIN_2_5 // Actual ALS Gain of 2.60
// GAIN_1_67 // Actual ALS Gain of 1.72
// GAIN_1_25 // Actual ALS Gain of 1.28
// GAIN_1 // Actual ALS Gain of 1.01
// GAIN_40 // Actual ALS Gain of 40
Serial.println(sensor.getAmbientLight(GAIN_1));
// Get Distance and report in mm
Serial.print("Distance measured (mm) = ");
Serial.println(sensor.getDistance());
delay(500);
};
void printIdentification(struct VL6180xIdentification *temp)
{
Serial.print("Model ID = ");
Serial.println(temp->idModel);
Serial.print("Model Rev = ");
Serial.print(temp->idModelRevMajor);
Serial.print(".");
Serial.println(temp->idModelRevMinor);
Serial.print("Module Rev = ");
Serial.print(temp->idModuleRevMajor);
Serial.print(".");
Serial.println(temp->idModuleRevMinor);
Serial.print("Manufacture Date = ");
Serial.print((temp->idDate >> 3) & 0x001F);
Serial.print("/");
Serial.print((temp->idDate >> 8) & 0x000F);
Serial.print("/1");
Serial.print((temp->idDate >> 12) & 0x000F);
Serial.print(" Phase: ");
Serial.println(temp->idDate & 0x0007);
Serial.print("Manufacture Time (s)= ");
Serial.println(temp->idTime * 2);
Serial.println();
Serial.println();
}