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.

Group Assignments

..

Link : week 13 Group Assignment

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 API is a JavaScript API that allows web applications to communicate with serial devices, such as microcontrollers, over a serial connection. It enables developers to read from and write to serial ports directly from the browser, making it easier to interact with hardware devices without the need for additional software or drivers.

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


          <!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 for directional controls */
          #UpButton {
              background-color: red;
              position: fixed;
              left: 15%;
              top: 50%;
              width: 100px;
              height: 100px;
              border-radius: 20%;
          }
          #UpButton:active {
              scale: 0.9;
          }
          #LeftButton {
              background-color: yellow;
              position: fixed;
              left: 5%;
              top: 60%;
              width: 100px;
              height: 100px;
              border-radius: 20%;
          }
          #LeftButton:active {
              scale: 0.9;
          }
          #RightButton {
              background-color: yellow;
              position: fixed;
              left: 25%;
              top: 60%;
              width: 100px;
              height: 100px;
              border-radius: 20%;
          }
          #RightButton:active {
              scale: 0.9;
          }
          #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 {
              background-color: rgb(10, 209, 77);
              position: fixed;
              width: 100px;
              height: 40px;
              border-radius: 10px;
          }
          #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 {
              width: 100%;
              height: 70px;
              background-color: grey;
              top: 0px;
          }
          #logo {
              width: 50px;
              padding-top: 10px;
          }
          #heading {
              padding-left: 50px;
              font-size: 30px;
              font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
          }
          
          /* Open and Close Buttons */
          #open, #close {
              position: fixed;
              width: 100px;
              height: 40px;
              border-radius: 10px;
          }
          #open {
              background-color: rgb(10, 209, 77);
              left: 8%;
              top: 30%;
          }
          #close {
              background-color: blue;
              left: 24%;
              top: 30%;
          }
          #open:active, #close:active {
              scale: 0.9;
          }
          
          /* Connect Button */
          #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 with logo and title -->
              <div id="header">
                  <img id="logo" src="/Game-Controller-PNG-Clipart.png">
                  <h3 id="heading">Control Center</h3>
              </div>
          
              <!-- 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>
              // Assign buttons to variables
              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 variables
              let port;
              let writer;
              let reader;
          
              // Connect to Serial Port (Web Serial API)
              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 a string over serial
              async function sendValue(value) {
                  if (!writer) return;
                  const encoder = new TextEncoder();
                  await writer.write(encoder.encode(value + '\n'));
              }
          
              // Button press/release effects
              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)'; }
          
              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 event listeners
              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);
          
              OpenButton.addEventListener('click', pressOpen);
              CloseButton.addEventListener('click', pressClose);
          
              // Keyboard support for control
              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();
              });
          
              // Serial commands from Open/Close buttons
              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

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 : 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 : 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 : 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);
                  }
                  

    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.