matteo morawski
matteo morawski

Reputation: 1

How to implement attenuation into a Bluetooth Mesh MATLAB script?

I am working on a Bluetooth LE mesh network project with various devices distributed in an urban environment. My goal is to determine the minimum node density per square kilometer required for the network to function effectively.

To explore this, I am using MATLAB, specifically the Bluetooth Toolbox library, to simulate a Bluetooth mesh network within a 200x200 meter area. In the simulation:

The script identifies active links between nodes based on the remaining power, which is calculated as the difference between the transmission power and the path loss. If the remaining power exceeds -70 dBm (the detection threshold for most receivers), the link is considered active. These active links are displayed on a figure using color grading.

However, i am encountering two major issues:

  1. I am struggling to correctly implement attenuation for BLE propagation using Free-Space Path Loss.
  2. Even when active links are present, the simulation often returns zero values for key metrics like Latency, Packet Loss Ratio (PLR), and Packet Delivery Ratio (PDR), which is not the expected outcome.

CODE:

% Initialize the wireless network simulator
networkSimulator = wirelessNetworkSimulator.init;

% Parameter to enable or disable the maximum distance constraint
maintainDistanceConstraint = true;  % Set to false to disable the maximum distance constraint

% Define the area and node parameters
areaSide = 200;
numNodes = 12;  % Total number of nodes
minReceivedPower = -70; % Minimum received power threshold in dBm
maxDistance = 70; % Maximum distance between nodes (valid only if maintainDistanceConstraint is true)
maxLinkDistance = 100; % Maximum distance to consider a link active
transmissionPower = 20; % Transmitted power in dBm

% Operating frequency of the Bluetooth LE signal (2.4 GHz)
frequency = 2.4e9;

% Function to calculate free space path loss
calculateFreeSpacePathLoss = @(distance, frequency) ...
    20 * log10(distance) + 20 * log10(frequency) - 147.55; % Result in dB

% Initialize the position matrix
nodePositions = zeros(numNodes, 3); % Including z = 0

% Random generation of rectangular obstacles (buildings) without overlap
numBuildings = 5; % Number of buildings
buildings = struct('x', [], 'y', [], 'width', [], 'height', []);
for i = 1:numBuildings
    validBuilding = false;
    maxAttempts = 1000;
    attempts = 0;

    while ~validBuilding && attempts < maxAttempts
        attempts = attempts + 1;

        % Random dimensions for the building (between 20x20 and 80x80 meters)
        width = 20 + rand * 60;
        height = 20 + rand * 60;

        % Random position for the building
        x = rand * (areaSide - width);
        y = rand * (areaSide - height);

        % Check for overlap with existing buildings
        overlap = false;
        for j = 1:i-1
            if ~(x + width < buildings(j).x || buildings(j).x + buildings(j).width < x || ...
                 y + height < buildings(j).y || buildings(j).y + buildings(j).height < y)
                overlap = true;
                break;
            end
        end

        if ~overlap
            validBuilding = true;
            buildings(i).x = x;
            buildings(i).y = y;
            buildings(i).width = width;
            buildings(i).height = height;
        end
    end

    if ~validBuilding
        warning("Could not place building %d without overlaps after %d attempts.", i, maxAttempts);
    end
end

% Node generation with or without maximum distance constraint
for i = 1:numNodes
    validPosition = false;
    nodeAttempts = 0;
    maxNodeAttempts = 1000;

    while ~validPosition && nodeAttempts < maxNodeAttempts
        nodeAttempts = nodeAttempts + 1;
        newPosition = rand(1, 2) * areaSide;

        if maintainDistanceConstraint && i > 1
            distances = sqrt(sum((nodePositions(1:i-1, 1:2) - newPosition).^2, 2));
            distanceSatisfied = any(distances <= maxDistance);
        else
            distanceSatisfied = true;
        end

        insideBuilding = false;
        for j = 1:numBuildings
            building = buildings(j);
            if newPosition(1) > building.x && newPosition(1) < (building.x + building.width) && ...
               newPosition(2) > building.y && newPosition(2) < (building.y + building.height)
                insideBuilding = true;
                break;
            end
        end

        if distanceSatisfied && ~insideBuilding
            validPosition = true;
            nodePositions(i, 1:2) = newPosition;
        end
    end

    if ~validPosition
        warning("Could not position node %d respecting constraints after %d attempts.", i, maxNodeAttempts);
    end
end

% Randomly select the transmitter and receiver
randomIndices = randperm(numNodes, 2);
transmitterIndex = randomIndices(1);
receiverIndex = randomIndices(2);

% Create the transmitter node
sourceNode = bluetoothLENode("broadcaster-observer", ...
    Name="Source Node", ...
    Position=nodePositions(transmitterIndex, :), ...
    TransmitterPower=transmissionPower); % Set transmission power

% Create the receiver node
destinationNode = bluetoothLENode("broadcaster-observer", ...
    Name="Destination Node", ...
    Position=nodePositions(receiverIndex, :), ...
    TransmitterPower=transmissionPower); % Set transmission power

% Configure Mesh profile for the transmitter node
cfgMeshSource = bluetoothMeshProfileConfig(ElementAddress="0001");
sourceNode.MeshConfig = cfgMeshSource;

% Configure Mesh profile for the receiver node
cfgMeshDestination = bluetoothMeshProfileConfig(ElementAddress="0002");
destinationNode.MeshConfig = cfgMeshDestination;

% Create relay nodes
relayNodes = cell(1, numNodes - 2); % Initialize the relay nodes array
relayCounter = 1;
for i = 1:numNodes
    if i ~= transmitterIndex && i ~= receiverIndex
        relayNode = bluetoothLENode("broadcaster-observer", ...
            Name=sprintf("Relay Node %d", relayCounter), ...
            Position=nodePositions(i, :), ...
            TransmitterPower=transmissionPower); % Set transmission power
        relayNodes{relayCounter} = relayNode; % Add relay node
        relayCounter = relayCounter + 1;
    end
end

% Create network traffic
traffic = networkTrafficOnOff(OnTime=inf, DataRate=1, PacketSize=15, GeneratePacket=true);
addTrafficSource(sourceNode, traffic, SourceAddress="0001", DestinationAddress="0002", TTL=10);

% Create the `nodes` array
nodes = [{sourceNode}, relayNodes, {destinationNode}];
addNodes(networkSimulator, [nodes{:}]);

% Calculate active links and received power
linkMatrix = zeros(numNodes); % Adjacency matrix
linkPower = zeros(numNodes, numNodes); % Residual power for links
minResidualPower = inf; % Minimum power value
maxResidualPower = -inf; % Maximum power value

fprintf("\nActive links in the mesh network:\n"); 

for i = 1:numNodes
    %{
    - Check the distance between nodes.
    - Check for obstacles (buildings) on the link.
    - Calculate received power considering path loss.
    - Register the link as active if the received power exceeds the threshold.
    - Update the minimum and maximum residual power values.
    - Print active link information.
    %}
    for j = 1:numNodes
        if i ~= j
            distance = pdist2(nodePositions(i, :), nodePositions(j, :));
            if distance <= maxLinkDistance
                % Check if a building is between the nodes
                buildingAttenuation = false;
                midX = (nodePositions(i, 1) + nodePositions(j, 1)) / 2;
                midY = (nodePositions(i, 2) + nodePositions(j, 2)) / 2;

                for k = 1:numBuildings
                    building = buildings(k);
                    if midX > building.x && midX < (building.x + building.width) && ...
                       midY > building.y && midY < (building.y + building.height)
                        buildingAttenuation = true;
                        break;
                    end
                end

                if ~buildingAttenuation
                    % Calculate path loss
                    pathLoss = calculateFreeSpacePathLoss(distance, frequency);
                    receivedPower = transmissionPower - pathLoss;

                    if receivedPower >= minReceivedPower
                        linkMatrix(i, j) = 1; % Active link
                        linkPower(i, j) = receivedPower;
                        minResidualPower = min(minResidualPower, receivedPower);
                        maxResidualPower = max(maxResidualPower, receivedPower);
                        fprintf("Node %d -> Node %d: Distance = %.2f m, Received Power = %.2f dBm\n", ...
                            i, j, distance, receivedPower);
                    end
                end
            end
        end
    end
end
% Run the simulation
simulationTime = 10;
run(networkSimulator, simulationTime);

% Retrieve and display statistics
sourceStats = statistics(sourceNode);
destinationStats = statistics(destinationNode);
relayStats = cellfun(@statistics, relayNodes, 'UniformOutput', false);

disp("Transmitter node statistics:");
disp(sourceStats);
disp("Receiver node statistics:");
disp(destinationStats);

% Calculate and display KPIs
latency = kpi(sourceNode, destinationNode, "latency", Layer="App");
plr = kpi(sourceNode, destinationNode, "PLR", Layer="App");
pdr = kpi(sourceNode, destinationNode, "PDR", Layer="App");

fprintf("\nBluetooth Mesh Network KPIs:\n");
fprintf("Latency: %.2f ms\n", latency * 1000); % Converted to milliseconds
fprintf("Packet Loss Ratio (PLR): %.2f\n", plr);
fprintf("Packet Delivery Ratio (PDR): %.2f\n", pdr);

% Visualize the mesh network
figure;
hold on;

% Draw buildings
for i = 1:numBuildings
    rectangle('Position', [buildings(i).x, buildings(i).y, buildings(i).width, buildings(i).height], ...
              'FaceColor', [0.5 0.5 0.5], 'EdgeColor', 'k');
end

% Draw nodes
for i = 1:numNodes
    if i == transmitterIndex
        scatter(nodePositions(i, 1), nodePositions(i, 2), 250, 'r', 'filled'); % Transmitter (red)
    elseif i == receiverIndex
        scatter(nodePositions(i, 1), nodePositions(i, 2), 250, 'g', 'filled'); % Receiver (green)
    else
        scatter(nodePositions(i, 1), nodePositions(i, 2), 200, 'b', 'filled'); % Other nodes (blue)
    end
end

% Draw links
for i = 1:numNodes
    for j = 1:numNodes
        if linkMatrix(i, j) == 1
            powerNorm = (linkPower(i, j) - minResidualPower) / ...
                        (maxResidualPower - minResidualPower);
            linkColor = [1 - powerNorm, powerNorm, 0]; % Gradient from red to green
            plot([nodePositions(i, 1), nodePositions(j, 1)], ...
                 [nodePositions(i, 2), nodePositions(j, 2)], '-', ...
                 'Color', linkColor, 'LineWidth', 2);
        end
    end
end

title('Distribution of Nodes, Buildings, and Active Links in the Bluetooth Mesh Network');
xlabel('X Position (meters)');
ylabel('Y Position (meters)');
xlim([0 areaSide]);
ylim([0 areaSide]);
grid on;
axis equal;
hold off;

enter image description here

Currently, my approach is as follows:

I am trying to adjust the simulation to only process data and compute metrics using the active links, but i am unsure how to implement this next step. I also know from the official MATLAB documentation that there is a way to account for attenuation directly using built-in library functions, but i am struggling to integrate this feature into the programming logic.

What i expect is for the script to compute and return realistic, non-zero values for Latency, Packet Loss Ratio (PLR), and Packet Delivery Ratio (PDR) when the transmitter and receiver are actively linked.

Upvotes: 0

Views: 27

Answers (0)

Related Questions