Akash Fab Academy

Week 14

Interface and Application Programming

This weeks Assignment is to write an application that interfaces a user with an input &/or output device that you made.

For this week my idea was to make an interface for my final project which should be an HTML page which can send my input data to a micro controller and get data back from the micro controller.

For this I had made a simple wire frame for the interface. Here the controls are button are used to control the motors also to control the direction.It also has two switches to control the opening and closing of the door.I have also added some additional buttons to control other functions.

Image 1

Learning

For the first two days of the week our instructors give a class about the basics of the JavaScript and how to make a simple interface using HTML and CSS After we were introduced to web usb , web serial and web socket

Web Serial

Web Serial is a web API that allows websites to directly communicate with serial devices (like microcontrollers, sensors, and other hardware) through the user's computer using a serial port (such as USB or UART). With Web Serial, developers can build web applications that interact with hardware devices in real-time, without needing additional software or drivers. This is especially useful for IoT projects, robotics, and embedded systems programming. The API is available in modern Chromium-based browsers (like Chrome and Edge) and requires user permission to access connected devices for security reasons.

AI Prompt: Give a brief about web serial in paragraph

Web USB

Web USB API is a JavaScript API that allows web applications to communicate with USB devices directly from the browser. It provides a way for developers to access and interact with USB peripherals, such as microcontrollers, printers, and other USB-enabled devices, without the need for additional drivers or software.

AI Prompt: Give a brief about web USB in paragraph

Web Socket

WebSocket is a communication protocol that provides full-duplex communication channels over a single TCP connection. It is designed to be used in real-time web applications, allowing for efficient and low-latency data exchange between a client (usually a web browser) and a server.

AI Prompt: Give a brief about web socket in paragraph

Test 1

First i wanted to learn the basics of the JavaScript and how web usb works for this i took an interface that our instructors made.The provided HTML and JavaScript code implements a simple web-based interface that communicates with an ESP32 microcontroller using the Web Serial API. It allows users to connect or disconnect from the ESP32, send custom text messages, and toggle an LED via serial communication directly from the browser. The interface includes buttons for connecting/disconnecting the serial port, a text input for sending messages, and a toggle button that switches an LED state by sending binary signals ("0" or "1"). Data received from the ESP32 is displayed in a text area in real time.


          <!doctype html>
        <html lang="en">
          <head>
            <meta charset="UTF-8" />
            <link rel="icon" type="image/svg+xml" href="/vite.svg" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>ESP32 Web Serial</title>
            
            <!-- Font Awesome Icons -->
            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
                  integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA=="
                  crossorigin="anonymous"
                  referrerpolicy="no-referrer" />
            
            <style>
              :root {
                font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
                line-height: 1.5;
                font-weight: 400;
                color-scheme: light dark;
                color: rgba(255, 255, 255, 0.87);
                background-color: #242424;
                font-synthesis: none;
                text-rendering: optimizeLegibility;
                -webkit-font-smoothing: antialiased;
                -moz-osx-font-smoothing: grayscale;
              }

              body {
                background-color: #e5e5f7;
                background-image: radial-gradient(#444df726 0.9px, #ffffffb0 0.9px);
                background-size: 18px 18px;
                margin: 0;
                min-width: 320px;
                min-height: 100vh;
              }

              .header {
                background-color: white;
                padding: 1px 2rem;
                height: 5rem;
                color: #213547;
              }

              .main {
                height: 91vh;
                display: flex;
                justify-content: center;
                align-items: center;
              }

              .window {
                background-color: white;
                padding: 20px 30px;
                box-shadow: 1px 2px 10px 1px #00000029;
                border-radius: 12px;
              }

              .window span {
                font-weight: 600;
              }

              .window div:nth-child(1) {
                display: flex;
                align-items: center;
              }

              .window div:nth-child(2) {
                padding: 20px 0px;
                min-width: 30vw;
              }

              .window div:nth-child(3) {
                display: flex;
                align-items: center;
              }

              .window div:nth-child(3) input[type="file"] {
                display: none;
              }

              .window textarea {
                width: 100%;
                background-color: #e5e5f796;
                border: 0;
                box-shadow: inset 0px 0px 10px 1px #00000007;
                border-radius: 5px;
              }

              .window button {
                transition: 0.5s;
              }

              .disconnectBtn {
                display: none;
              }

              .lightBtn {
                color: #bfc20da8;
              }

              #input {
                background: #fff;
                color: black;
                padding-inline: 5px;
                padding-block: 5px;
                border: 1px solid rgba(0, 0, 0, 0.192);
                border-radius: 5px;
                outline: none;
              }

              button {
                border-radius: 8px;
                border: 1px solid transparent;
                font-size: 1em;
                font-weight: 500;
                font-family: inherit;
                background-color: #1a1a1a;
                cursor: pointer;
                transition: border-color 0.25s;
              }

              button:hover {
                border-color: #646cff;
              }

              button:focus,
              button:focus-visible {
                outline: 4px auto -webkit-focus-ring-color;
              }

              @media (prefers-color-scheme: light) {
                :root {
                  color: #213547;
                  background-color: #ffffff;
                }

                a:hover {
                  color: #747bff;
                }

                button {
                  background-color: #f9f9f9;
                }
              }
            </style>
          </head>
          <body>
            <div class="header">
              <h2>Web Serial <img src="https://img.icons8.com/?size=256&id=41183&format=png" style="width: 25px;" alt=""></h2>
            </div>
            
            <div class="main">
              <div class="window">
                <div class="btnDiv">
                  <span>ESP32</span>
                  <button id="serial" style="margin-left:auto;transition: 0.5s;padding: 5px 25px;"><i class="fa-solid fa-plug-circle-check" style="color: #34ea58;"></i> Connect</button>
                  <button id="disconnect" style="display: none;margin-left:auto;transition: 0.5s;padding: 5px 25px;"><i class="fa-solid fa-plug-circle-xmark" style="color: #c92626;"></i> Disconnect</button>
                  <button id="toggle" class="" style="margin-left:10px;padding: 5px 25px;"><i class="fa-solid fa-lightbulb" style="color: #c20d0da8"></i></button>
                </div>
                
                <div>
                  <textarea id="outputMsg" cols="30" rows="10" disabled></textarea>
                </div>
                
                <div>
                  <input type="text" id="input" placeholder="Enter your Data Here..."/>
                  <button id="upload" class="" style="margin-left: auto;padding: 5px 25px;"><i class="fa-solid fa-upload"></i></button>
                </div>
              </div>
            </div>

            <script>
              let port;
              let writer;
              let reader;
              let toggle;

              // Connect to serial port
              async function connectToSerial() {
                port = await navigator.serial.requestPort();
                await port.open({ baudRate: 9600 });

                writer = port.writable.getWriter();
                reader = port.readable.getReader();
                const decoder = new TextDecoder();

                while (true) {
                  const { value, done } = await reader.read();
                  if (done) break;
                  const string = decoder.decode(value);
                  document.getElementById('outputMsg').textContent += string;
                }
              }

              // Send input to serial device
              async function sendMessage() {
                const input = document.getElementById('input').value;
                if (!writer) return;

                const encoder = new TextEncoder();
                await writer.write(encoder.encode(input + '\n'));
                document.getElementById('input').value = "";
              }

              // Toggle LED using serial signal
              async function toggleLED() {
                if (!writer) return;

                const dataToSend = toggle ? '1' : '0';
                const encoder = new TextEncoder();
                writer.write(encoder.encode(dataToSend)).then(() => {
                  if (dataToSend === '0') {
                    document.getElementById('toggle').innerHTML = '<i class="fa-solid fa-lightbulb" style="color: #c20d0da8"></i>';
                  } else {
                    document.getElementById('toggle').innerHTML = '<i class="fa-solid fa-lightbulb" style="color: #2f5917"></i>';
                  }
                  toggle = !toggle;
                });
              }

              // Event listeners
              document.getElementById('serial').addEventListener('click', connectToSerial);
              document.getElementById('upload').addEventListener('click', sendMessage);
              document.getElementById('toggle').addEventListener('click', toggleLED);
            </script>
          </body>
        </html>

        

From this code i was able to understand the basics of the JavaScript and how the web usb.

Test 2

Here i have creates a simple interactive web page where users can type their name into an input field, and the entered text is instantly displayed within a heading. As the user types into the text box labeled #name, the value updates the content of a with the ID namer, which is embedded in the sentence “My Name is.” Additionally, if the name exceeds four characters, the displayed name text changes color to red for visual feedback. A button labeled "Click Me" is also included on the page, although it currently has no attached functionality.


              <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Test Page</title>
        </head>

        <style>
            #name {
                position: fixed;
                width: 300px;
                height: 30px;
                top: 50%;
                left: 30%;
                font-size: 20px;
                border: 1px solid black;
            }

            #MyName {
                display: flex;
                font-size: 20px;
            }

            #clickMe {
                position: fixed;
                top: 60%;
                left: 45%;
                width: 100px;
                height: 30px;
            }
        </style>

        <body>
            <div id="MyName">
                <h1>My Name is <span id="namer"></span></h1>
            </div>

            <button id="clickMe" style="width: 100px; height: 30px">Click Me</button>

            <input type="text" id="name" />

            <script>
                document.getElementById('name').addEventListener('input', function(event) {
                    document.getElementById('namer').innerText = event.target.value;
                    const array = event.target.value;

                    if (array.length > 4) {
                        document.getElementById('namer').style.color = 'red';
                    }
                });
            </script>
        </body>
        </html>

            
        

Interface

Here i was planning to create an interface where i would be able to display the 2D location of the robot using the data from UWB sensor and the interface can be used to control the the direction of the move movement it can also control the doors and other function on the robot. For this i started by first making buttons using HTML then Then using CSS i made them design of the button and also placed them in the desired locations.After that I have also added the clicking actions to the buttons.

As the next step i defined functions for each actions then as the next step i added the functions to the buttons like when the button is pressed a specific action is triggered and when the button is released another action is triggered. in addition to that i have also mapped some keys from keyboard so that the buttons can be controlled using the buttons from keyboard

AI Prompt: Add the comments to the code below


          <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test Page</title>
</head>

<style>
/* ----------- BUTTON STYLES ----------- */

/* Up button styling */
#UpButton {
    background-color: red;
    position: fixed;
    left: 15%;
    top: 50%;
    width: 100px;
    height: 100px;
    border-radius: 20%;
}

/* Visual scale down when pressed */
#UpButton:active {
    scale: 0.9;
}

/* Left button styling */
#LeftButton {
    background-color: yellow;
    position: fixed;
    left: 5%;
    top: 60%;
    width: 100px;
    height: 100px;
    border-radius: 20%;
}

#LeftButton:active {
    scale: 0.9;
}

/* Right button styling */
#RightButton {
    background-color: yellow;
    position: fixed;
    left: 25%;
    top: 60%;
    width: 100px;
    height: 100px;
    border-radius: 20%;
}

#RightButton:active {
    scale: 0.9;
}

/* Down button styling */
#DownButton {
    background-color: red;
    position: fixed;
    left: 15%;
    top: 70%;
    width: 100px;
    height: 100px;
    border-radius: 20%;
}

#DownButton:active {
    scale: 0.9;
}

/* Utility buttons (Home, Go, Clear) */
#Home, #Go, #Clear {
    background-color: rgb(10, 209, 77);
    position: fixed;
    width: 100px;
    height: 40px;
    border-radius: 10px;
}

/* Individual positioning */
#Home {
    left: 60%;
    top: 80%;
}
#Go {
    left: 75%;
    top: 80%;
}
#Clear {
    left: 90%;
    top: 80%;
}

#Home:active, #Go:active, #Clear:active {
    scale: 0.9;
}

/* ----------- HEADER STYLES ----------- */

/* Header container */
#header {
    width: 100%;
    height: 70px;
    background-color: grey;
    top: 0px;
}

/* Logo inside header */
#logo {
    width: 50px;
    padding-top: 10px;
}

/* Title text inside header */
#heading {
    padding-left: 50px;
    font-size: 30px;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

/* ----------- OPEN, CLOSE & CONNECT ----------- */

/* Open/Close button styling */
#open, #close {
    position: fixed;
    width: 100px;
    height: 40px;
    border-radius: 10px;
}

/* Open = green, Close = blue */
#open {
    background-color: rgb(10, 209, 77);
    left: 8%;
    top: 30%;
}
#close {
    background-color: blue;
    left: 24%;
    top: 30%;
}

/* Scale on click */
#open:active, #close:active {
    scale: 0.9;
}

/* Connect button styling */
#connect {
    background-color: grey;
    position: fixed;
    left: 24%;
    top: 40%;
    width: 100px;
    height: 40px;
    border-radius: 10px;
}
</style>

<body style="margin: 0px; width: 100vw; height: 100dvh;">

    <!-- Header section -->
    <div id="header">
        <img id="logo" src="/Game-Controller-PNG-Clipart.png">
        <h3 id="heading">Control Center</h3>
    </div>

    <!-- Control buttons -->
    <button id="UpButton">Up</button>
    <button id="LeftButton">Left</button>
    <button id="RightButton">Right</button>
    <button id="DownButton">Down</button>
    <button id="Home">Home</button>
    <button id="Go">Go</button>
    <button id="Clear">Clear</button>
    <button id="open">Open</button>
    <button id="close">Close</button>
    <button id="connect" onclick="connectToSerial()">Connect</button>

    <script>
    // Get references to buttons
    const UpButton = document.getElementById('UpButton');
    const LeftButton = document.getElementById('LeftButton');
    const RightButton = document.getElementById('RightButton');
    const DownButton = document.getElementById('DownButton');
    const HomeButton = document.getElementById('Home');
    const GoButton = document.getElementById('Go');
    const ClearButton = document.getElementById('Clear');
    const OpenButton = document.getElementById('open');
    const CloseButton = document.getElementById('close');

    // Serial communication setup
    let port;
    let writer;
    let reader;

    // Connect to serial port using Web Serial API
    async function connectToSerial() {
        port = await navigator.serial.requestPort(); // Request port from user
        await port.open({ baudRate: 9600 }); // Open port with baud rate

        writer = port.writable.getWriter();
        reader = port.readable.getReader();

        const decoder = new TextDecoder();

        // Continuously read incoming serial data
        while (true) {
            const { value, done } = await reader.read();
            if (done) break;

            const string = decoder.decode(value);
            document.getElementById('outputMsg').textContent += string;
        }
    }

    // Function to send a string to serial port
    async function sendValue(value) {
        if (!writer) return;
        const encoder = new TextEncoder();
        await writer.write(encoder.encode(value + '\n')); // Append newline
    }

    // Functions for visual feedback on button press/release
    function pressup() { UpButton.style.backgroundColor = 'blue'; }
    function releaseup() { UpButton.style.backgroundColor = 'red'; }

    function pressleft() { LeftButton.style.backgroundColor = 'blue'; }
    function releaseleft() { LeftButton.style.backgroundColor = 'yellow'; }

    function pressright() { RightButton.style.backgroundColor = 'blue'; }
    function releaseright() { RightButton.style.backgroundColor = 'yellow'; }

    function pressdown() { DownButton.style.backgroundColor = 'blue'; }
    function releasedown() { DownButton.style.backgroundColor = 'red'; }

    function PressHome() { HomeButton.style.backgroundColor = 'blue'; }
    function releaseHome() { HomeButton.style.backgroundColor = 'rgb(10, 209, 77)'; }

    function PressGo() { GoButton.style.backgroundColor = 'blue'; }
    function releaseGo() { GoButton.style.backgroundColor = 'rgb(10, 209, 77)'; }

    function PressClear() { ClearButton.style.backgroundColor = 'blue'; }
    function releaseClear() { ClearButton.style.backgroundColor = 'rgb(10, 209, 77)'; }

    // Toggle between open and close visual states
    function pressOpen() {
        OpenButton.style.backgroundColor = 'blue';
        CloseButton.style.backgroundColor = 'rgb(10, 209, 77)';
    }
    function pressClose() {
        CloseButton.style.backgroundColor = 'blue';
        OpenButton.style.backgroundColor = 'rgb(10, 209, 77)';
    }

    // Mouse interactions for directional buttons
    UpButton.addEventListener('mousedown', pressup);
    document.addEventListener('mouseup', releaseup);

    LeftButton.addEventListener('mousedown', pressleft);
    LeftButton.addEventListener('mouseup', releaseleft);

    RightButton.addEventListener('mousedown', pressright);
    RightButton.addEventListener('mouseup', releaseright);

    DownButton.addEventListener('mousedown', pressdown);
    DownButton.addEventListener('mouseup', releasedown);

    HomeButton.addEventListener('mousedown', PressHome);
    HomeButton.addEventListener('mouseup', releaseHome);

    GoButton.addEventListener('mousedown', PressGo);
    GoButton.addEventListener('mouseup', releaseGo);

    ClearButton.addEventListener('mousedown', PressClear);
    ClearButton.addEventListener('mouseup', releaseClear);

    // Click events for door control
    OpenButton.addEventListener('click', pressOpen);
    CloseButton.addEventListener('click', pressClose);

    // Keyboard controls for directional actions
    document.addEventListener('keydown', function(event) {
        if (event.key === 'ArrowUp' || event.key.toLowerCase() === 'w') pressup();
        if (event.key === 'ArrowLeft' || event.key.toLowerCase() === 'a') pressleft();
        if (event.key === 'ArrowRight' || event.key.toLowerCase() === 'd') pressright();
        if (event.key === 'ArrowDown' || event.key.toLowerCase() === 's') pressdown();
        if (event.key.toLowerCase() === 'h') PressHome();
        if (event.key.toLowerCase() === 'g') PressGo();
        if (event.key.toLowerCase() === 'c') PressClear();
    });

    document.addEventListener('keyup', function(event) {
        if (event.key === 'ArrowUp' || event.key.toLowerCase() === 'w') releaseup();
        if (event.key === 'ArrowLeft' || event.key.toLowerCase() === 'a') releaseleft();
        if (event.key === 'ArrowRight' || event.key.toLowerCase() === 'd') releaseright();
        if (event.key === 'ArrowDown' || event.key.toLowerCase() === 's') releasedown();
        if (event.key.toLowerCase() === 'h') releaseHome();
        if (event.key.toLowerCase() === 'g') releaseGo();
        if (event.key.toLowerCase() === 'c') releaseClear();
    });

    // Send serial commands when open/close buttons are clicked
    document.getElementById('open').addEventListener('click', () => {
        sendValue("1");
    });

    document.getElementById('close').addEventListener('click', () => {
        sendValue("0");
    });
    </script>
</body>
</html>

        

The video below shows the control interface here when the page loads the door will be always closed so the close button is always ble and when the open button is pressed the button trs blue and when the close button is pressed the button turns blue.

The other buttons when pressed the button turns blue and when released the button turns back to its original color also when the keys on the keyboard which is mapped to the button the buttons turns blue.I have also provided a connect button which is used to initialize the web usb and show the port that are connected

I had used chat gpt to learn how to connect the interface with the Keyboard inputs and Used the example code provided by instructor for getting the needed syntax for creating the interface

Hardware Setup

For the hardware setup i used the same that was made for UWB that was made in the Week 11 i used the built in LED on the custom UWB board.

Image 1

This is a video that shows the LED being controlled using the interface.

UWB testing and calibration

For this week i wanted to get data from the UWB sensor to the RP2040 and this data should be shared to an interface so that the data can be visualized,But from the week 10 i was not able to get proper accurate data from the sensor.

For getting more accurate readings from the UWB sensor I followed the Maker fab documentation and calibrated the UWB sensor

  1. Download the Jim Remington DW1000 library to replace the original DW1000 library.
  2. Upload the ESP32_UWB_setup_tag.ino sketch to the Tag device after making some changes in the sketch so that it works properly.
  3. Place the Tag and Anchor at a fixed distance her i kept both devices at 1 m apart.
  4. Open ESP32_anchor_autocalibrate.ino, set the distance to 1 meters, and upload the sketch to the Anchor device.
  5. Record the Adelay value from the Anchor's serial output.
  6. Update the Adelay parameter in the Anchor firmware (default value is 16384) for further measurements.
  7. Image 1

    Tag Code

    This code is for setting up a UWB (Ultra-Wideband) distance measurement system using DW1000 modules. It includes three parts: one for the tag, one for calibrating anchors, and one for the final anchor setup. The tag sends signals and receives distance readings from anchors. The calibration code adjusts each anchor’s antenna delay to match a known distance, improving accuracy. Once calibrated, anchors use the final code with the correct delay values to measure distances from the tag. The system uses SPI communication and special libraries to handle the ranging process and device connections.

    AI Prompt : Give a brief about the code

    
                
    
                  // currently tag is module #5
                  // The purpose of this code is to set the tag address and antenna delay to default.
                  // this tag will be used for calibrating the anchors.
                  
                  #include <SPI.h>                // SPI communication library
                  #include "DW1000Ranging.h"      // DW1000 ranging functions
                  #include "DW1000.h"             // DW1000 core functions
                  
                  // Connection pin definitions
                  const uint8_t PIN_RST = 27;     // Reset pin for DW1000
                  const uint8_t PIN_IRQ = 26;     // Interrupt pin for DW1000
                  const uint8_t PIN_SS = 1;       // SPI Chip Select pin
                  
                  // TAG antenna delay defaults to 16384
                  // Leftmost two bytes define the "short address"
                  char tag_addr[] = "7D:00:22:EA:82:60:3B:9C";  // Tag address
                  
                  void setup()
                  {
                    Serial.begin(115200);         // Start serial communication
                    delay(1000);                  // Give some time to stabilize
                  
                    // Initialize SPI and DW1000 communication
                    SPI.begin();
                    DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ); // Reset, CS, IRQ pins
                  
                    // Attach callback functions for events
                    DW1000Ranging.attachNewRange(newRange);              // When new range is received
                    DW1000Ranging.attachNewDevice(newDevice);            // When a new device is detected
                    DW1000Ranging.attachInactiveDevice(inactiveDevice);  // When a device becomes inactive
                  
                    // Start the module as a TAG
                    // Do not assign a random short address — use the one specified
                    DW1000Ranging.startAsTag(tag_addr, DW1000.MODE_LONGDATA_RANGE_LOWPOWER, false);
                  }
                  
                  void loop()
                  {
                    // Continuously handle ranging communication
                    DW1000Ranging.loop();
                  }
                  
                  // Callback when a new distance measurement is available
                  void newRange()
                  {
                    Serial.print(DW1000Ranging.getDistantDevice()->getShortAddress(), HEX);
                    Serial.print(",");
                    Serial.println(DW1000Ranging.getDistantDevice()->getRange());
                  }
                  
                  // Callback when a new device is added
                  void newDevice(DW1000Device *device)
                  {
                    Serial.print("Device added: ");
                    Serial.println(device->getShortAddress(), HEX);
                  }
                  
                  // Callback when a device is no longer active
                  void inactiveDevice(DW1000Device *device)
                  {
                    Serial.print("delete inactive device: ");
                    Serial.println(device->getShortAddress(), HEX);
                  }
                  

    Anchor Calibration Code

    This code is for setting up a UWB (Ultra-Wideband) distance measurement system using DW1000 modules. It includes three parts: one for the tag, one for calibrating anchors, and one for the final anchor setup. The tag sends signals and receives distance readings from anchors. The calibration code adjusts each anchor’s antenna delay to match a known distance, improving accuracy. Once calibrated, anchors use the final code with the correct delay values to measure distances from the tag. The system uses SPI communication and special libraries to handle the ranging process and device connections.

    AI Prompt: Give a brief about the code

    
                  #include <SPI.h>                  // Include SPI communication library
                  #include "DW1000Ranging.h"        // Include DW1000 UWB Ranging library
                  #include "DW1000.h"               // Include core DW1000 driver library
                  
                  // Define the pin assignments
                  const uint8_t PIN_RST = 27; // Reset pin
                  const uint8_t PIN_IRQ = 34; // Interrupt pin
                  const uint8_t PIN_SS = 4;   // SPI chip select pin
                  
                  // Set this anchor's UWB address
                  char this_anchor_addr[] = "84:00:22:EA:82:60:3B:9C";
                  
                  // The target distance from tag to this anchor (in meters), converted from inches
                  float this_anchor_target_distance = 1;
                  
                  // Initial antenna delay value (used for calibration)
                  uint16_t this_anchor_Adelay = 16600;
                  
                  // Step size used for binary search during Adelay calibration
                  uint16_t Adelay_delta = 100;
                  
                  void setup()
                  {
                    Serial.begin(115200);        // Start the serial monitor
                    while (!Serial);             // Wait until the Serial monitor is ready
                  
                    SPI.begin();                 // Initialize SPI communication
                    DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ); // Initialize DW1000 with given pins
                  
                    Serial.print("Starting Adelay "); 
                    Serial.println(this_anchor_Adelay);
                  
                    Serial.print("Measured distance "); 
                    Serial.println(this_anchor_target_distance);
                  
                    // Set the initial antenna delay value
                    DW1000.setAntennaDelay(this_anchor_Adelay);
                  
                    // Attach callback functions
                    DW1000Ranging.attachNewRange(newRange);          // Called when a new range measurement is available
                    DW1000Ranging.attachNewDevice(newDevice);        // Called when a new device is detected
                    DW1000Ranging.attachInactiveDevice(inactiveDevice); // Called when a device becomes inactive
                  
                    // Start the DW1000 module in anchor mode
                    DW1000Ranging.startAsAnchor(this_anchor_addr, DW1000.MODE_LONGDATA_RANGE_LOWPOWER, false);
                  }
                  
                  void loop()
                  {
                    // Continuously handle ranging communication
                    DW1000Ranging.loop();
                  }
                  
                  // Callback: Called when a new range is available
                  void newRange()
                  {
                    static float last_delta = 0.0;
                    Serial.print(DW1000Ranging.getDistantDevice()->getShortAddress(), DEC);
                  
                    float dist = DW1000Ranging.getDistantDevice()->getRange(); // Measured distance
                  
                    Serial.print(",");
                    Serial.print(dist);
                  
                    if (Adelay_delta < 3) {
                      // Stop calibration when the step is small enough
                      Serial.print(", final Adelay ");
                      Serial.println(this_anchor_Adelay);
                      while (1); // Halt execution
                    }
                  
                    // Calculate the error between measured and target distances
                    float this_delta = dist - this_anchor_target_distance;
                  
                    // If sign of delta changes, reduce step size
                    if (this_delta * last_delta < 0.0) Adelay_delta = Adelay_delta / 2;
                    last_delta = this_delta;
                  
                    // Adjust Adelay based on measurement
                    if (this_delta > 0.0) this_anchor_Adelay += Adelay_delta;
                    else this_anchor_Adelay -= Adelay_delta;
                  
                    Serial.print(", Adelay = ");
                    Serial.println(this_anchor_Adelay);
                  
                    // Apply the new antenna delay
                    DW1000.setAntennaDelay(this_anchor_Adelay);
                  }
                  
                  // Callback: Called when a new device is detected
                  void newDevice(DW1000Device *device)
                  {
                    Serial.print("Device added: ");
                    Serial.println(device->getShortAddress(), HEX);
                  }
                  
                  // Callback: Called when a device becomes inactive
                  void inactiveDevice(DW1000Device *device)
                  {
                    Serial.print("delete inactive device: ");
                    Serial.println(device->getShortAddress(), HEX);
                  }
                  

    Anchor Code

    This code is for setting up a UWB (Ultra-Wideband) distance measurement system using DW1000 modules. It includes three parts: one for the tag, one for calibrating anchors, and one for the final anchor setup. The tag sends signals and receives distance readings from anchors. The calibration code adjusts each anchor’s antenna delay to match a known distance, improving accuracy. Once calibrated, anchors use the final code with the correct delay values to measure distances from the tag. The system uses SPI communication and special libraries to handle the ranging process and device connections.

    AI Prompt: Give a brief about the code

    
                  // Anchor #4 setup
                  
                  // Be sure to edit anchor_addr and select the previously calibrated anchor delay
                  // Naming convention: anchors 1, 2, 3... use the lowest byte of the MAC address as 81, 82, 83...
                  
                  #include <SPI.h>                   // SPI library for communication
                  #include "DW1000Ranging.h"         // High-level DW1000 ranging functions
                  #include "DW1000.h"                // Low-level DW1000 control
                  
                  // Leftmost two bytes define the "short address"
                  char anchor_addr[] = "84:00:5B:D5:A9:9A:E2:9C"; // Anchor #4
                  
                  // Calibrated antenna delay for this specific anchor
                  uint16_t Adelay = 16570;
                  
                  // Previously determined antenna delays:
                  // #1 16630
                  // #2 16610
                  // #3 16607
                  // #4 16580
                  
                  // Calibration distance used for testing
                  float dist_m = 1; // in meters
                  
                  // Pin assignments
                  const uint8_t PIN_RST = 6;   // Reset pin
                  const uint8_t PIN_IRQ = 28;  // Interrupt pin
                  const uint8_t PIN_SS = 1;    // SPI chip select pin
                  
                  void setup()
                  {
                    Serial.begin(115200);             // Start serial communication
                    delay(1000);                      // Wait for Serial Monitor to connect
                    Serial.println("Anchor config and start");
                    Serial.print("Antenna delay ");
                    Serial.println(Adelay);
                    Serial.print("Calibration distance ");
                    Serial.println(dist_m);
                  
                    // Initialize SPI and DW1000
                    SPI.begin();
                    DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ); // Reset, CS, IRQ pins
                  
                    // Set the antenna delay - only for anchors
                    DW1000.setAntennaDelay(Adelay);
                  
                    // Attach callback functions
                    DW1000Ranging.attachNewRange(newRange);              // Called when a new range is received
                    DW1000Ranging.attachNewDevice(newDevice);            // Called when a new device is detected
                    DW1000Ranging.attachInactiveDevice(inactiveDevice);  // Called when a device becomes inactive
                  
                    // Start this device as an anchor (no random short address)
                    DW1000Ranging.startAsAnchor(anchor_addr, DW1000.MODE_LONGDATA_RANGE_LOWPOWER, false);
                  
                    // Alternative modes (commented):
                    // DW1000Ranging.startAsAnchor(ANCHOR_ADD, DW1000.MODE_SHORTDATA_FAST_LOWPOWER);
                    // DW1000Ranging.startAsAnchor(ANCHOR_ADD, DW1000.MODE_LONGDATA_FAST_LOWPOWER);
                    // DW1000Ranging.startAsAnchor(ANCHOR_ADD, DW1000.MODE_SHORTDATA_FAST_ACCURACY);
                    // DW1000Ranging.startAsAnchor(ANCHOR_ADD, DW1000.MODE_LONGDATA_FAST_ACCURACY);
                    // DW1000Ranging.startAsAnchor(ANCHOR_ADD, DW1000.MODE_LONGDATA_RANGE_ACCURACY);
                  }
                  
                  void loop()
                  {
                    // Handle ongoing DW1000 communication and ranging
                    DW1000Ranging.loop();
                  }
                  
                  // Callback when a new range is available
                  void newRange()
                  {
                    Serial.print(DW1000Ranging.getDistantDevice()->getShortAddress(), HEX);
                    Serial.print(", ");
                  
                    #define NUMBER_OF_DISTANCES 1
                    float dist = 0.0;
                  
                    // Average over NUMBER_OF_DISTANCES readings
                    for (int i = 0; i < NUMBER_OF_DISTANCES; i++) {
                      dist += DW1000Ranging.getDistantDevice()->getRange();
                    }
                  
                    dist = dist / NUMBER_OF_DISTANCES;
                    Serial.println(dist);
                  }
                  
                  // Callback when a new device connects
                  void newDevice(DW1000Device *device)
                  {
                    Serial.print("Device added: ");
                    Serial.println(device->getShortAddress(), HEX);
                  }
                  
                  // Callback when a device becomes inactive
                  void inactiveDevice(DW1000Device *device)
                  {
                    Serial.print("Delete inactive device: ");
                    Serial.println(device->getShortAddress(), HEX);
                  }
                  

    Group Assignments

    As part of this week's group assignment, we explored multiple tools such as Kodular, Pygame, Processing, Flutter, and HTML with CSS.

    Link : week 14 Group Assignment

    Conclusion

    For this week i learned about the basics of JavaScript & I have tested the use of webserial in JavaScript ,I made a simple interface using HTML,CSS & JavaScript and made a simple interface. I tried to calibrate the UWB sensor and get a good result, But i was not able to get a good satisfactory result from the data.