Sparkfun artemis thing plus board + sparkfun Qwiic ToF Imager - VL53L5CX

I have experience working with the Arduino IDE; however, I am now being asked to use MATLAB for real-time acquisition of the 8×8 distance matrix, visualization (heatmaps, 2D/3D plots), and data logging. I do not know how to interface the SparkFun Artemis Thing Plus board with MATLAB. It would be really helpful if someone could guide me through this process

Because Artemis Thing Plus is not directly supported by MATLAB’s Arduino Support Package (which only supports specific boards like Uno, Mega, Due, etc.) you’ll want to pre-program the board to perform serial output

Upload this to the Artemis using the Arduino IDE

/*
  Artemis Thing Plus - VL53L5CX 8x8 Distance Matrix to MATLAB
  Hardware: SparkFun Artemis Thing Plus + Qwiic VL53L5CX
  Communication: Serial USB at 115200 baud
*/

#include <Wire.h>
#include <SparkFun_VL53L5CX_Library.h>

SparkFun_VL53L5CX myImager;
VL53L5CX_ResultsData measurementData;

// Configuration
const uint8_t RESOLUTION = 8; // 8x8 matrix
const uint8_t RANGING_FREQ = 15; // 15Hz for 8x8 mode
const unsigned long SAMPLE_INTERVAL = 67; // ~15Hz in milliseconds

bool imagerReady = false;
unsigned long lastSampleTime = 0;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10); // Wait for serial port to connect
  
  Serial.println("Artemis_Thing_Plus_VL53L5CX_Ready");
  
  Wire.begin();
  Wire.setClock(400000); // Fast I2C
  
  // Initialize VL53L5CX
  if (myImager.begin() == false) {
    Serial.println("ERROR:SensorNotDetected");
    while (1) delay(10);
  }
  
  // Configure for 8x8 mode at 15Hz
  myImager.setResolution(RESOLUTION * RESOLUTION);
  myImager.setRangingFrequency(RANGING_FREQ);
  
  if (myImager.startRanging() == false) {
    Serial.println("ERROR:RangingStartFailed");
    while (1) delay(10);
  }
  
  imagerReady = true;
  Serial.println("STATUS:Ready");
}

void loop() {
  if (!imagerReady) return;
  
  // Check if it's time for next sample
  if (millis() - lastSampleTime < SAMPLE_INTERVAL) return;
  lastSampleTime = millis();
  
  // Check if data is ready
  if (myImager.isDataReady()) {
    if (myImager.getRangingData(&measurementData)) {
      // Send matrix in compact format for MATLAB
      // Format: "MAT,[d00],[d01],...,[d77]\n"
      Serial.print("MAT");
      
      for (int y = 0; y < RESOLUTION; y++) {
        for (int x = 0; x < RESOLUTION; x++) {
          int index = (y * RESOLUTION) + x;
          int16_t distance = measurementData.distance_mm[index];
          
          Serial.print(",");
          // Handle invalid readings
          if (distance < 0 || distance > 4000) {
            Serial.print("NaN");
          } else {
            Serial.print(distance);
          }
        }
      }
      Serial.println(); // Newline terminator
    }
  }
}

Then run back over to MATLAB and try this script:

%% MATLAB Real-Time 8x8 Distance Matrix Acquisition
% Hardware: SparkFun Artemis Thing Plus + VL53L5CX
% Features: Real-time heatmap, 3D surface plot, and data logging

clear; clc; close all;

%% Configuration
PORT = 'COM4';          % Change to your actual COM port
BAUDRATE = 115200;
MATRIX_SIZE = 8;
MAX_RANGE_MM = 4000;    % Maximum sensor range
UPDATE_INTERVAL = 0.05; % 50ms display update

% Data logging settings
LOG_FILE = 'distance_matrix_data.mat';
SAVE_INTERVAL = 100;    % Save every 100 samples
samplesCollected = 0;
dataLog = [];

%% Initialize Serial Port
% Use modern serialport object (R2019b+)
try
    s = serialport(PORT, BAUDRATE);
    configureTerminator(s, "LF");
    flush(s);
    disp('Serial port opened successfully');
catch ME
    error('Failed to open serial port. Check COM port and connections.');
end

% Wait for Arduino initialization
disp('Waiting for Artemis Thing Plus to initialize...');
pause(3);
flush(s);

%% Setup Real-Time Visualization
figure('Name', 'VL53L5CX 8x8 Distance Matrix', 'Position', [100 100 1400 500]);

% Subplot 1: Heatmap
subplot(1, 3, 1);
hHeatmap = imagesc(zeros(MATRIX_SIZE, MATRIX_SIZE));
title('Real-Time Distance Heatmap');
xlabel('X Zone');
ylabel('Y Zone');
colorbar;
colormap(jet);
clim([0 MAX_RANGE_MM]);
axis image;

% Subplot 2: 3D Surface
subplot(1, 3, 2);
hSurf = surf(zeros(MATRIX_SIZE, MATRIX_SIZE));
title('3D Distance Surface');
xlabel('X');
ylabel('Y');
zlabel('Distance (mm)');
zlim([0 MAX_RANGE_MM]);
colorbar;
shading interp;

% Subplot 3: Time series of center pixel
subplot(1, 3, 3);
centerData = [];
hPlot = plot(NaN, NaN, 'b-', 'LineWidth', 1.5);
title('Center Pixel (4,4) Distance Over Time');
xlabel('Sample');
ylabel('Distance (mm)');
ylim([0 MAX_RANGE_MM]);
grid on;
hold on;

%% Main Acquisition Loop
disp('Starting data acquisition... Press Ctrl+C to stop');
tic;

try
    while true
        % Check for available data
        if s.NumBytesAvailable > 0
            line = readline(s);
            line = strtrim(line);
            
            % Parse data if it starts with "MAT"
            if startsWith(line, "MAT")
                % Parse comma-separated values
                dataStr = split(line, ',');
                
                if length(dataStr) >= (MATRIX_SIZE^2 + 1)
                    % Extract distance values
                    matrixData = zeros(MATRIX_SIZE, MATRIX_SIZE);
                    idx = 1;
                    
                    for y = 1:MATRIX_SIZE
                        for x = 1:MATRIX_SIZE
                            valStr = dataStr{idx + 1}; % Skip "MAT" prefix
                            
                            % Handle NaN values
                            if strcmp(valStr, "NaN")
                                matrixData(y, x) = NaN;
                            else
                                matrixData(y, x) = str2double(valStr);
                            end
                            idx = idx + 1;
                        end
                    end
                    
                    % Update visualizations
                    updateVisualizations(matrixData, hHeatmap, hSurf, hPlot, centerData);
                    
                    % Log data
                    samplesCollected = samplesCollected + 1;
                    timestamp = toc;
                    dataLog(samplesCollected).time = timestamp;
                    dataLog(samplesCollected).matrix = matrixData;
                    
                    % Periodic save
                    if mod(samplesCollected, SAVE_INTERVAL) == 0
                        save(LOG_FILE, 'dataLog', 'samplesCollected');
                        fprintf('Saved %d samples to %s\n', samplesCollected, LOG_FILE);
                    end
                    
                    % Update center pixel history for time plot
                    centerData(end+1) = matrixData(4, 4);
                    if length(centerData) > 200 % Keep last 200 points
                        centerData = centerData(end-199:end);
                    end
                end
            end
        end
        
        pause(UPDATE_INTERVAL);
    end
    
catch ME
    disp(['Error: ' ME.message]);
end

%% Cleanup
disp('Closing connection...');
save(LOG_FILE, 'dataLog', 'samplesCollected');
clear s;
disp(['Data saved to ' LOG_FILE]);

%% Helper Function
function updateVisualizations(matrixData, hHeatmap, hSurf, hPlot, centerData)
    % Update heatmap
    hHeatmap.CData = matrixData;
    
    % Update 3D surface
    hSurf.ZData = matrixData;
    
    % Update time series plot
    if ~isempty(centerData)
        hPlot.XData = 1:length(centerData);
        hPlot.YData = centerData;
        xlim([max(1, length(centerData)-200) length(centerData)+10]);
    end
    
    drawnow limitrate;
end

That should get ya most of the way there

Thank you so much. It worked.

1 Like